{"record":{"id":"8a9bf9625da7f850","repo":"gastownhall/beads","slug":"create-add-waits-for-w","errorCode":null,"errorMessage":"create: add waits-for: %w","messagePattern":"create: add waits-for: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/issue.go","lineNumber":1054,"sourceCode":"\t\t}\n\t\tdepSourceIsWisp, err := u.isWispID(ctx, dep.IssueID)\n\t\tif err != nil {\n\t\t\treturn result, fmt.Errorf(\"create: determine dep source tier for %s: %w\", dep.IssueID, err)\n\t\t}\n\t\tif err := u.depRepo.Insert(ctx, dep, actor, DepInsertOpts{UseWispsTable: depSourceIsWisp}); err != nil {\n\t\t\treturn result, fmt.Errorf(\"create: add dep %s -> %s: %w\", dep.IssueID, dep.DependsOnID, err)\n\t\t}\n\t\tresult.PostCreateWrites = true\n\t}\n\n\tif params.WaitsFor != nil {\n\t\t// Spawner identity is the depends_on_id; metadata carries the gate.\n\t\tdep, err := types.NewWaitsForDependency(issue.ID, params.WaitsFor.SpawnerID, params.WaitsFor.Gate)\n\t\tif err != nil {\n\t\t\treturn result, fmt.Errorf(\"create: marshal waits-for meta: %w\", err)\n\t\t}\n\t\tif err := u.depRepo.Insert(ctx, dep, actor, DepInsertOpts{UseWispsTable: useWisp}); err != nil {\n\t\t\treturn result, fmt.Errorf(\"create: add waits-for: %w\", err)\n\t\t}\n\t\tresult.PostCreateWrites = true\n\t}\n\n\treturn result, nil\n}\n\nfunc validateExplicitIDPrefix(id, prefix, allowedPrefixes string) error {\n\tif strings.HasPrefix(id, prefix+\"-\") {\n\t\treturn nil\n\t}\n\tfor _, allowed := range strings.Split(allowedPrefixes, \",\") {\n\t\tallowed = strings.TrimSpace(allowed)\n\t\tif allowed != \"\" && strings.HasPrefix(id, allowed+\"-\") {\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn fmt.Errorf(\"%w: issue ID %s does not match configured prefix %s\", storage.ErrPrefixMismatch, id, prefix)","sourceCodeStart":1036,"sourceCodeEnd":1072,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/issue.go#L1036-L1072","documentation":"Wraps a failure from depRepo.Insert when persisting the waits-for dependency during issue creation. The gate metadata was marshaled successfully but the database insert of the dependency row failed. Causes mirror ordinary dependency inserts: constraint violations, unknown referenced IDs, or storage/driver errors.","triggerScenarios":"Calling Create with params.WaitsFor set where the depRepo.Insert call into the issues (or wisps) deps table fails — invalid spawner ID reference, constraint violation, or DB error.","commonSituations":"WaitsFor pointing at a spawner ID that doesn't exist or was deleted; transient Dolt/storage failures; wrong storage tier (wisp vs durable) routing mismatch.","solutions":["Verify the SpawnerID refers to an existing issue","Check the wrapped inner error for the storage-level cause","Confirm wisp/durable tier consistency (useWisp matches both issue and spawner)","Retry transient storage errors; inspect driver health if persistent"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if params.WaitsFor != nil {\n    if _, err := uc.GetIssue(ctx, params.WaitsFor.SpawnerID); err != nil {\n        return fmt.Errorf(\"spawner %s must exist before waits-for\", params.WaitsFor.SpawnerID)\n    }\n}","typeGuard":null,"tryCatchPattern":"_, err := uc.Create(ctx, params, actor)\nif err != nil && strings.Contains(err.Error(), \"add waits-for\") {\n    // inspect wrapped storage cause; retry only on transient errors\n    if isTransient(err) { backoffRetry() }\n}","preventionTips":["Ensure the spawner issue exists before setting WaitsFor","Keep wisp and durable issues in separate create calls","Validate IDs before create","Retry with backoff on transient driver errors only"],"tags":["storage","waits-for","dependency-insert","go"],"backgroundTag":"dependency-insert-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}