{"record":{"id":"f1f7c617313695f4","repo":"gastownhall/beads","slug":"get-next-child-id-query-existing-children-w","errorCode":null,"errorMessage":"get next child ID: query existing children: %w","messagePattern":"get next child ID: query existing children: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/child_id.go","lineNumber":33,"sourceCode":"\tvar lastChild int\n\t//nolint:gosec // G201: counterTable is one of two hardcoded constants.\n\terr := tx.QueryRowContext(ctx,\n\t\tfmt.Sprintf(\"SELECT last_child FROM %s WHERE parent_id = ?\", counterTable),\n\t\tparentID).Scan(&lastChild)\n\tif err == sql.ErrNoRows {\n\t\tlastChild = 0\n\t} else if err != nil {\n\t\treturn \"\", fmt.Errorf(\"get next child ID: read counter: %w\", err)\n\t}\n\n\t//nolint:gosec // G201: issueTable is one of two hardcoded constants.\n\trows, err := tx.QueryContext(ctx, fmt.Sprintf(`\n\t\tSELECT id FROM %s\n\t\tWHERE id LIKE CONCAT(?, '.%%')\n\t\t  AND id NOT LIKE CONCAT(?, '.%%.%%')\n\t`, issueTable), parentID, parentID)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"get next child ID: query existing children: %w\", err)\n\t}\n\tdefer rows.Close()\n\n\tfor rows.Next() {\n\t\tvar id string\n\t\tif err := rows.Scan(&id); err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"get next child ID: scan child row: %w\", err)\n\t\t}\n\t\t_, childNum, ok := ParseHierarchicalID(id)\n\t\tif ok && childNum > lastChild {\n\t\t\tlastChild = childNum\n\t\t}\n\t}\n\tif err := rows.Err(); err != nil {\n\t\treturn \"\", fmt.Errorf(\"get next child ID: iterate children: %w\", err)\n\t}\n\n\tnextChild := lastChild + 1","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/child_id.go#L15-L51","documentation":"GetNextChildIDTx queries all existing child IDs of a parent (id LIKE 'parent.%') to recover the true max child number, and wraps query execution failures with \"get next child ID: query existing children: %w\". This guards against a stale or missing counter row. The error means the SELECT on the issues table failed before any rows were read.","triggerScenarios":"Calling ExecuteCreate when: the LIKE query against the issues table fails from a missing/corrupted table, the transaction is aborted, the context is cancelled, or the connection is lost.","commonSituations":"Sub-issue creation against a DB missing the issues table (bad routing/table constants), aborted transaction reuse after an earlier failed statement, cancellation during bulk child creation, remote Dolt connectivity loss.","solutions":["Retry the transaction if the wrapped error indicates a connection or lock-wait failure.","Verify the database schema is current (issues table and counter table both present).","Roll back the transaction on this error rather than continuing; the tx is unusable after failure.","Check context deadlines if bulk operations are timing out."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if ctx.Err() != nil { return ctx.Err() }","typeGuard":null,"tryCatchPattern":"if err != nil {\n    tx.Rollback()\n    if isTransient(err) { return retry(err) }\n    return fmt.Errorf(\"child lookup failed: %w\", err)\n}","preventionTips":["Keep create-transactions short to avoid aborts and lock waits.","Run bd doctor to confirm table integrity before bulk child creation.","Avoid cancelling bd mid-create; let the transaction finish.","Retry transient connection errors; the read is idempotent."],"tags":["database","sql","child-ids","query"],"backgroundTag":"sql-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}