{"record":{"id":"7702dfe48ed99419","repo":"micro/go-micro","slug":"flow-verify-requires-a-body-step","errorCode":null,"errorMessage":"flow: Verify requires a body step","messagePattern":"flow: Verify requires a body step","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"flow/verify.go","lineNumber":69,"sourceCode":"// JSON field named \"feedback\" (or VerifyFeedbackField). When all attempts fail,\n// it returns the last output without error, annotated with verification fields so\n// the run can keep the bounded failure outcome in its state:\n// \"verification_passed\": false, \"verification_feedback\", and\n// \"verification_attempts\".\nfunc Verify(body StepFunc, grader Grader, opts ...VerifyOption) StepFunc {\n\to := VerifyOptions{MaxAttempts: 2, FeedbackField: \"feedback\"}\n\tfor _, op := range opts {\n\t\top(&o)\n\t}\n\tif o.MaxAttempts <= 0 {\n\t\to.MaxAttempts = 2\n\t}\n\tif o.FeedbackField == \"\" {\n\t\to.FeedbackField = \"feedback\"\n\t}\n\treturn func(ctx context.Context, in State) (State, error) {\n\t\tif body == nil {\n\t\t\treturn in, fmt.Errorf(\"flow: Verify requires a body step\")\n\t\t}\n\t\tif grader == nil {\n\t\t\treturn in, fmt.Errorf(\"flow: Verify requires a grader\")\n\t\t}\n\t\tcur := in\n\t\tlast := in\n\t\tfeedback := \"\"\n\t\tfor attempt := 1; attempt <= o.MaxAttempts; attempt++ {\n\t\t\tif err := ctx.Err(); err != nil {\n\t\t\t\treturn last, err\n\t\t\t}\n\t\t\tif feedback != \"\" {\n\t\t\t\tvar err error\n\t\t\t\tcur, err = stateWithField(cur, o.FeedbackField, feedback)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn last, err\n\t\t\t\t}\n\t\t\t}","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/flow/verify.go#L51-L87","documentation":"flow.Verify wraps a body step with a retry-and-grade loop; this error is returned at run time when the wrapped body step is nil. Verify cannot retry a step that does not exist, so the returned State is passed through unchanged with this error. It indicates a programming mistake in how Verify was called, not a runtime failure of the body itself.","triggerScenarios":"Calling flow.Verify(nil, grader) or Verify with a body variable that was declared but never assigned, so the returned step function returns \"flow: Verify requires a body step\" on first execution.","commonSituations":"Conditionally assigning the body step and a branch leaving it nil; passing the result of a factory that can return nil; refactoring that removed the body but kept the Verify wrapper.","solutions":["Pass a non-nil Step function as the body argument to flow.Verify.","Guard the call site: only wrap with Verify when the body was successfully constructed.","Fail fast at construction time by checking body != nil before calling Verify instead of at run time."],"exampleFix":"// before\nvar body flow.StepFunc // nil\nreturn flow.Verify(body, grader)\n// after\nif body == nil {\n    return nil, fmt.Errorf(\"body step not configured\")\n}\nreturn flow.Verify(body, grader)","handlingStrategy":"validation","validationCode":"if body == nil {\n    return nil, errors.New(\"verify: body step must be configured\")\n}\nreturn flow.Verify(body, grader), nil","typeGuard":"func bodyConfigured(f flow.StepFunc) bool { return f != nil }","tryCatchPattern":"out, err := verifiedStep(ctx, in)\nif err != nil && strings.Contains(err.Error(), \"Verify requires a body step\") {\n    // configuration bug: fix flow wiring, not a runtime condition\n}","preventionTips":["Never declare a StepFunc variable without assigning it before Verify.","Make step construction functions return (StepFunc, error) so nil bodies surface early.","Cover every Verify wiring with a smoke test that executes the flow once."],"tags":["go","flow","verify","nil-argument"],"backgroundTag":"nil-argument","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}