{"record":{"id":"5d0a51d86ce780db","repo":"gastownhall/beads","slug":"get-ready-work-compute-deferred-parent-children","errorCode":null,"errorMessage":"get ready work: compute deferred parent children: %w","messagePattern":"get ready work: compute deferred parent children: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/db/ready_work.go","lineNumber":35,"sourceCode":"}\n\n// buildReadyWorkOrder orders by the sort_* aliases projected by\n// sqlbuild.UnionSortColumnsSQL, since ready work always sorts at the UNION\n// outer query here.\nfunc buildReadyWorkOrder(policy types.SortPolicy) sqlbuild.ReadyWorkOrder {\n\treturn sqlbuild.BuildReadyWorkOrder(policy, \"sort_created\", \"sort_priority\")\n}\n\n// buildReadyWorkPredicates computes the ID sets the ready-work WHERE clause\n// needs (children of deferred parents, parent descendants), then delegates\n// the clause text to sqlbuild so both stacks share ready semantics. Unlike\n// the classic stack, ORDER BY and LIMIT are applied at the UNION outer query.\nfunc (r *issueSQLRepositoryImpl) buildReadyWorkPredicates(ctx context.Context, filter types.WorkFilter, tables filterTables) (*readyWorkPredicates, error) {\n\tvar inputs sqlbuild.ReadyWorkWhereInputs\n\tif !filter.IncludeDeferred {\n\t\tdeferredChildIDs, dcErr := r.getChildrenOfDeferredParents(ctx)\n\t\tif dcErr != nil {\n\t\t\treturn nil, fmt.Errorf(\"get ready work: compute deferred parent children: %w\", dcErr)\n\t\t}\n\t\tinputs.DeferredChildIDs = deferredChildIDs\n\t}\n\tif filter.ParentID != nil {\n\t\tdescendantIDs, descErr := r.getDescendantIDs(ctx, *filter.ParentID, 0)\n\t\tif descErr != nil {\n\t\t\treturn nil, fmt.Errorf(\"get parent descendants: %w\", descErr)\n\t\t}\n\t\tinputs.ParentDescendantIDs = descendantIDs\n\t}\n\n\twhereSQL, args, err := sqlbuild.BuildReadyWorkWhere(filter, tables, inputs)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &readyWorkPredicates{whereSQL: whereSQL, args: args}, nil\n}\n","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/ready_work.go#L17-L53","documentation":"Wraps failures from getChildrenOfDeferredParents while buildReadyWorkPredicates assembles the ID sets for the ready-work WHERE clause. When a work filter does not include deferred items, the library must first find children of currently-deferred parents to exclude them. If that probe/query fails, get ready work cannot produce a trustworthy ready list and aborts with this wrap.","triggerScenarios":"Calling bd ready / GetReadyWork with IncludeDeferred=false while the deferred-parent existence probe or the deferred-children queries fail (connection error, missing table that is not an optional wisp table, SQL error).","commonSituations":"Schema drift where `issues`/`dependencies` tables are missing or renamed; DB connectivity problems during ready-work computation; engine errors in the deferred-parent probe queries.","solutions":["Check the wrapped cause (\"deferred parents: ...\") for the underlying SQL error","Verify core tables (issues, wisps, dependencies, wisp_dependencies) exist in the database","Retry if transient connectivity; check server health","As a workaround, call with IncludeDeferred=true to skip deferred-parent computation"],"exampleFix":"// before: failing filter\nfilter := types.WorkFilter{} // IncludeDeferred=false triggers the deferred-parent pass\n// after: skip deferred-parent computation when acceptable\nfilter := types.WorkFilter{IncludeDeferred: true}","handlingStrategy":"try-catch","validationCode":"// verify core tables before computing ready work\nfor _, t := range []string{\"issues\", \"wisps\", \"dependencies\", \"wisp_dependencies\"} {\n\tvar c int\n\terr := db.QueryRow(\"SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = ?\", t).Scan(&c)\n\tif err != nil || c == 0 { return fmt.Errorf(\"missing table %s\", t) }\n}","typeGuard":"func isDeferredChildrenError(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"compute deferred parent children\")\n}","tryCatchPattern":"ready, err := repo.GetReadyWork(ctx, filter)\nif isDeferredChildrenError(err) {\n\t// fall back to including deferred items, which skips this computation\n\tfilter.IncludeDeferred = true\n\tready, err = repo.GetReadyWork(ctx, filter)\n}","preventionTips":["Run schema migrations before computing ready work","Verify core tables exist for your deployment mode","Use IncludeDeferred=true when deferred filtering is not required","Monitor DB health before batch ready-work calls"],"tags":["database","ready-work","deferred","query"],"backgroundTag":"ready-work-computation-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}