gastownhall/beads · error

get dependent records from %s: %w

Error message

get dependent records from %s: %w

What it means

This error wraps the failure of the QueryContext call that reads dependent (inbound) dependency rows from either the 'dependencies' or 'wisp_dependencies' table inside getDependentRecordsIntoFromTable. It is thrown when the database rejects or cannot execute the SELECT (bad SQL, missing table, connection/context failure). The wrapped %s names which dependency table failed, and %w preserves the underlying driver error.

Source

Thrown at internal/storage/issueops/dependency_queries.go:195

func getDependentRecordsIntoFromTable(ctx context.Context, tx DBTX, depTable string, targetIDs []string, seen map[string]bool, result map[string][]*types.Dependency) error {
	for start := 0; start < len(targetIDs); start += queryBatchSize {
		end := start + queryBatchSize
		if end > len(targetIDs) {
			end = len(targetIDs)
		}
		batch := targetIDs[start:end]
		placeholders := make([]string, len(batch))
		args := make([]any, len(batch))
		for i, id := range batch {
			placeholders[i] = "?"
			args[i] = id
		}
		rows, err := tx.QueryContext(ctx, fmt.Sprintf(
			`SELECT id, issue_id, %s AS depends_on_id, type, created_at, created_by, metadata, thread_id
			 FROM %s WHERE %s ORDER BY %s`,
			DepTargetExpr, depTable, depTargetIn("", strings.Join(placeholders, ",")), DepTargetExpr), args...)
		if err != nil {
			return fmt.Errorf("get dependent records from %s: %w", depTable, err)
		}
		for rows.Next() {
			dep, scanErr := scanDependentRow(rows)
			if scanErr != nil {
				_ = rows.Close()
				return fmt.Errorf("get dependent records: scan: %w", scanErr)
			}
			// De-dup by row id (depid): the wisp copy of a promoted edge carries
			// the same id as the durable copy scanned first, so skip the repeat.
			if seen[dep.ID] {
				continue
			}
			seen[dep.ID] = true
			result[dep.DependsOnID] = append(result[dep.DependsOnID], dep)
		}
		_ = rows.Close()
		if err := rows.Err(); err != nil {
			return fmt.Errorf("get dependent records: rows: %w", err)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check the wrapped driver error to identify the root cause (table missing vs connection vs syntax).
  2. Run schema migrations so both dependencies and wisp_dependencies exist (bd should create them; verify with a schema dump).
  3. If wisp_dependencies is legitimately absent in your deployment, the caller already tolerates isTableNotExistError for the optional table — verify the table-exists detection matches your driver's error string.
  4. Retry the operation if the wrapped error is transient (connection reset, context deadline); otherwise fix the environment.
  5. Upgrade or downgrade to matching storage-schema versions of the binary.

Example fix

// before (caller sees opaque failure)
deps, err := GetDependentRecordsForIssuesInTx(ctx, tx, ids)
if err != nil { log.Fatal(err) }
// after (distinguish missing-table from real failure)
deps, err := GetDependentRecordsForIssuesInTx(ctx, tx, ids)
if err != nil {
    if isTableNotExistError(err) { /* run migrations */ }
    log.Fatalf("dependent records read failed: %v", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: verify tables exist before the call
var one int
if err := tx.QueryRowContext(ctx, "SELECT 1 FROM wisp_dependencies LIMIT 1").Scan(&one); err != nil && !isTableNotExistError(err) {
    return fmt.Errorf("wisp_dependencies unavailable: %w", err)
}

Type guard

func isDependencyTableReady(ctx context.Context, tx DBTX, table string) bool {
    var one int
    err := tx.QueryRowContext(ctx, "SELECT 1 FROM "+table+" LIMIT 1").Scan(&one)
    return err == nil || isTableNotExistError(err)
}

Try / catch

deps, err := GetDependentRecordsForIssuesInTx(ctx, tx, targetIDs)
if err != nil {
    var tblErr *TableNotExistError
    if errors.As(err, &tblErr) || isTableNotExistError(err) {
        // optional table path: degrade gracefully
    } else if isTransientNetError(err) {
        // retry with backoff
    } else {
        return err
    }
}

Prevention

When it happens

Trigger: Calling GetDependentRecordsForIssuesInTx when the target dependency table does not exist (unmigrated database), the SQL fails (e.g. driver-specific syntax issue with DepTargetExpr), the context is canceled, or the connection to the database drops mid-query.

Common situations: Running a new binary against an old database missing wisp_dependencies; a corrupted or partially-migrated Dolt/SQLite schema; network interruption to a remote database; context timeout during a large batched read.

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/2e96f04c8985e987. Report an issue: GitHub.