{"record":{"id":"0b43e113b741f680","repo":"micro/go-micro","slug":"flow-s-checkpoint-save-w","errorCode":null,"errorMessage":"flow %s checkpoint save: %w","messagePattern":"flow (.+?) checkpoint save: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"flow/steps.go","lineNumber":716,"sourceCode":"func applyVerificationRecord(record *StepRecord, verification Verification) {\n\tif verification.Passed {\n\t\trecord.VerificationStatus = \"passed\"\n\t}\n\tif verification.Feedback != \"\" {\n\t\trecord.VerificationNote = truncate(verification.Feedback, 200)\n\t\tif !verification.Passed {\n\t\t\trecord.VerificationStatus = \"failed\"\n\t\t}\n\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","sourceCodeStart":698,"sourceCodeEnd":734,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/flow/steps.go#L698-L734","documentation":"f.save persists the run record through the configured Checkpoint. If checkpoint.Save fails, the save method logs the error and returns it wrapped as 'flow %s checkpoint save: %w' so callers of Start/Resume/ResumeWith see both the flow name and the underlying store error. Note save is a no-op returning nil when no checkpoint is configured, so this error only occurs on an actual save path with a configured store.","triggerScenarios":"Any run state transition (started, step progress, waiting, done, failed) calling f.save when the Checkpoint backend's Save returns an error: store unreachable, serialization failure, permission denied, context canceled/deadline exceeded.","commonSituations":"Store service down or network partitioned during a run; store bucket/prefix misconfigured or lacking write permissions; run record too large for the backend; context deadline from the caller expiring mid-save; auth token expired for a hosted store.","solutions":["Read the wrapped cause after the flow name in the message and fix the underlying checkpoint store error (connectivity, auth, permissions).","Verify the Checkpoint store configuration: address, bucket/prefix, and credentials.","Increase the context deadline for the flow operation so saves aren't cut off by caller timeouts.","Add health checks/retries on the store backend, and alert on the logged 'Flow %s checkpoint save' error lines.","Confirm the Run record (State.Data, StepResults) fits backend limits; truncate large payloads."],"exampleFix":"// before\nf := flow.New(flow.Checkpoint(store.New(store.Nodes(\"bad-host:9999\"))))\n\n// after\nf := flow.New(flow.Checkpoint(store.New(\n  store.Nodes(\"localhost:6379\"),\n  store.Database(\"flows\"),\n))) // reachable, writable store","handlingStrategy":"retry","validationCode":"// verify store writability before building the flow\nr := store.New(store.Nodes(addr))\nif err := r.Write(ctx, \"healthcheck-key\", []byte(\"ok\")); err != nil {\n    return fmt.Errorf(\"checkpoint store not writable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := f.Start(ctx, in); err != nil {\n    var csErr *checkpointSaveError\n    if strings.Contains(err.Error(), \"checkpoint save: \") {\n        // transient store issue: backoff and retry the operation\n        return retryWithBackoff(ctx, func() error { _, err := f.Start(ctx2, in); return err })\n    }\n    return err\n}","preventionTips":["Add retries with backoff around checkpoint store operations in the backend implementation","Monitor the 'Flow %s checkpoint save' error log lines with alerting","Use durable, replicated stores for checkpoints in production","Keep run payloads small to avoid backend size limits","Ensure context deadlines comfortably exceed expected flow duration"],"tags":["go","flow","checkpoint","persistence","store"],"backgroundTag":"checkpoint-save-failed","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}