{"record":{"id":"33854d2559725ff6","repo":"gastownhall/beads","slug":"journal-snapshot-derived-is-blocked-from-s-w","errorCode":null,"errorMessage":"journal: snapshot derived is_blocked from %s: %w","messagePattern":"journal: snapshot derived is_blocked from (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/journal.go","lineNumber":233,"sourceCode":"\t}{\n\t\t{table: \"issues\", ids: issueIDs},\n\t\t{table: \"wisps\", ids: wispIDs},\n\t} {\n\t\tfor start := 0; start < len(target.ids); start += queryBatchSize {\n\t\t\tend := start + queryBatchSize\n\t\t\tif end > len(target.ids) {\n\t\t\t\tend = len(target.ids)\n\t\t\t}\n\t\t\tinClause, args := buildSQLInClause(target.ids[start:end])\n\t\t\t//nolint:gosec // table is one of the two hardcoded values above.\n\t\t\trows, err := tx.QueryContext(ctx,\n\t\t\t\tfmt.Sprintf(\"SELECT id, is_blocked FROM %s WHERE id IN (%s)\", target.table, inClause),\n\t\t\t\targs...)\n\t\t\tif err != nil {\n\t\t\t\tif optionalBlockedTable(target.table) && isTableNotExistError(err) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\treturn nil, fmt.Errorf(\"journal: snapshot derived is_blocked from %s: %w\", target.table, err)\n\t\t\t}\n\t\t\tfor rows.Next() {\n\t\t\t\tvar id string\n\t\t\t\tvar blocked int\n\t\t\t\tif err := rows.Scan(&id, &blocked); err != nil {\n\t\t\t\t\t_ = rows.Close()\n\t\t\t\t\treturn nil, fmt.Errorf(\"journal: scan derived is_blocked from %s: %w\", target.table, err)\n\t\t\t\t}\n\t\t\t\tsnapshot[blockedJournalKey{table: target.table, id: id}] = blocked != 0\n\t\t\t}\n\t\t\tif err := rows.Err(); err != nil {\n\t\t\t\t_ = rows.Close()\n\t\t\t\treturn nil, fmt.Errorf(\"journal: iterate derived is_blocked from %s: %w\", target.table, err)\n\t\t\t}\n\t\t\tif err := rows.Close(); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"journal: close derived is_blocked from %s: %w\", target.table, err)\n\t\t\t}\n\t\t}","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/journal.go#L215-L251","documentation":"captureBlockedJournalSnapshot wraps a SELECT of (id, is_blocked) from a blocked-tracking table. If the table is optional and the error is 'table not exist' it is tolerated; any other query failure is wrapped and aborts the journal snapshot, failing the enclosing transaction.","triggerScenarios":"The SELECT id, is_blocked FROM <table> WHERE id IN (...) fails: missing table that is not in the optional set, bad SQL, connection failure, or permission denial.","commonSituations":"Partial schema setup missing a dependency-tracking table; corrupted database; running with a schema from an incompatible version.","solutions":["Inspect the wrapped driver error to find which table/query failed","Run schema migration so all required blocked-tracking tables exist","If the table should be optional, verify it is listed in optionalBlockedTable so a missing table is tolerated","Check DB connectivity and permissions"],"exampleFix":"null","handlingStrategy":"try-catch","validationCode":"for _, t := range requiredBlockedTables {\n  var n int\n  db.QueryRow(\"SELECT COUNT(*) FROM information_schema.tables WHERE table_name = ?\", t).Scan(&n)\n  if n == 0 { /* migrate before calling journal paths */ }\n}","typeGuard":"null","tryCatchPattern":"snapshot, err := captureBlockedJournalSnapshot(ctx, tx)\nif err != nil {\n  if isTableNotExistError(err) { /* tolerate only if table is optional */ }\n  return fmt.Errorf(\"blocked snapshot failed: %w\", err)\n}","preventionTips":["Run full schema migrations; ensure optional tables are registered as optional","Verify is_blocked columns are NOT NULL integers","Check DB connectivity before bulk recompute operations"],"tags":["sql","journal","is-blocked","snapshot"],"backgroundTag":"sql-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}