{"record":{"id":"6df81821b0b007ce","repo":"micro/go-micro","slug":"flow-step-d-has-an-empty-name","errorCode":null,"errorMessage":"flow: step %d has an empty name","messagePattern":"flow: step (.+?) has an empty name","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"flow/steps.go","lineNumber":725,"sourceCode":"\t}\n}\n\nfunc (f *Flow) save(ctx context.Context, run Run) error {\n\tif f.checkpoint == nil {\n\t\treturn nil\n\t}\n\tif err := f.checkpoint.Save(ctx, run); err != nil {\n\t\tf.log.Logf(logger.ErrorLevel, \"Flow %s checkpoint save: %v\", f.name, err)\n\t\treturn fmt.Errorf(\"flow %s checkpoint save: %w\", f.name, err)\n\t}\n\treturn nil\n}\n\nfunc validateSteps(steps []Step) error {\n\tseen := make(map[string]struct{}, len(steps))\n\tfor i, step := range steps {\n\t\tif step.Name == \"\" {\n\t\t\treturn fmt.Errorf(\"flow: step %d has an empty name\", i)\n\t\t}\n\t\tif _, ok := seen[step.Name]; ok {\n\t\t\treturn fmt.Errorf(\"flow: duplicate step name %q\", step.Name)\n\t\t}\n\t\tseen[step.Name] = struct{}{}\n\t}\n\treturn nil\n}\n\nfunc stepIndex(steps []Step, name string) int {\n\tfor i, s := range steps {\n\t\tif s.Name == name {\n\t\t\treturn i\n\t\t}\n\t}\n\treturn -1\n}\n","sourceCodeStart":707,"sourceCodeEnd":743,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/flow/steps.go#L707-L743","documentation":"This error comes from flow.validateSteps, which iterates every step in a flow definition and rejects any step whose Name field is an empty string. The library requires named steps because step names are used for addressing, deduplication, and references between steps. It fires before the flow ever runs, at construction/validation time.","triggerScenarios":"Calling any flow-building/validation API that reaches validateSteps while a Step literal in the []Step slice has Name == \"\", e.g. flow steps declared as {Action: ...} without setting Name.","commonSituations":"Constructing steps programmatically and forgetting to set Name; building steps from config/YAML where a 'name:' key was omitted or empty; a step factory returning a zero-value Step.","solutions":["Set a unique non-empty Name on every Step in the slice passed to the flow builder.","If steps are loaded from config, validate the config before constructing the flow and report which step index is missing a name.","Add a helper constructor that requires a name parameter so a Step cannot be built without one."],"exampleFix":"// before\nsteps := []flow.Step{{Action: myAction}}\n// after\nsteps := []flow.Step{{Name: \"my-step\", Action: myAction}}","handlingStrategy":"validation","validationCode":"for i, s := range steps {\n    if s.Name == \"\" {\n        return fmt.Errorf(\"step %d: name must be non-empty\", i)\n    }\n}","typeGuard":"func hasValidNames(steps []flow.Step) bool {\n    for _, s := range steps {\n        if s.Name == \"\" {\n            return false\n        }\n    }\n    return true\n}","tryCatchPattern":null,"preventionTips":["Always construct steps via a constructor that requires a name argument.","Lint config files for required 'name' keys before building flows.","Add a unit test asserting every declared flow step has a non-empty unique name."],"tags":["go","flow","validation","configuration"],"backgroundTag":"missing-required-argument","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}