gastownhall/beads · error

journal: snapshot derived is_blocked from %s: %w

Error message

journal: snapshot derived is_blocked from %s: %w

What it means

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.

Source

Thrown at internal/storage/issueops/journal.go:233

	}{
		{table: "issues", ids: issueIDs},
		{table: "wisps", ids: wispIDs},
	} {
		for start := 0; start < len(target.ids); start += queryBatchSize {
			end := start + queryBatchSize
			if end > len(target.ids) {
				end = len(target.ids)
			}
			inClause, args := buildSQLInClause(target.ids[start:end])
			//nolint:gosec // table is one of the two hardcoded values above.
			rows, err := tx.QueryContext(ctx,
				fmt.Sprintf("SELECT id, is_blocked FROM %s WHERE id IN (%s)", target.table, inClause),
				args...)
			if err != nil {
				if optionalBlockedTable(target.table) && isTableNotExistError(err) {
					break
				}
				return nil, fmt.Errorf("journal: snapshot derived is_blocked from %s: %w", target.table, err)
			}
			for rows.Next() {
				var id string
				var blocked int
				if err := rows.Scan(&id, &blocked); err != nil {
					_ = rows.Close()
					return nil, fmt.Errorf("journal: scan derived is_blocked from %s: %w", target.table, err)
				}
				snapshot[blockedJournalKey{table: target.table, id: id}] = blocked != 0
			}
			if err := rows.Err(); err != nil {
				_ = rows.Close()
				return nil, fmt.Errorf("journal: iterate derived is_blocked from %s: %w", target.table, err)
			}
			if err := rows.Close(); err != nil {
				return nil, fmt.Errorf("journal: close derived is_blocked from %s: %w", target.table, err)
			}
		}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped driver error to find which table/query failed
  2. Run schema migration so all required blocked-tracking tables exist
  3. If the table should be optional, verify it is listed in optionalBlockedTable so a missing table is tolerated
  4. Check DB connectivity and permissions

Example fix

null
Defensive patterns

Strategy: try-catch

Validate before calling

for _, t := range requiredBlockedTables {
  var n int
  db.QueryRow("SELECT COUNT(*) FROM information_schema.tables WHERE table_name = ?", t).Scan(&n)
  if n == 0 { /* migrate before calling journal paths */ }
}

Type guard

null

Try / catch

snapshot, err := captureBlockedJournalSnapshot(ctx, tx)
if err != nil {
  if isTableNotExistError(err) { /* tolerate only if table is optional */ }
  return fmt.Errorf("blocked snapshot failed: %w", err)
}

Prevention

When it happens

Trigger: 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.

Common situations: Partial schema setup missing a dependency-tracking table; corrupted database; running with a schema from an incompatible version.

Understand the failure class

Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/33854d2559725ff6. Report an issue: GitHub.