gastownhall/beads · error

scan dependency: %w

Error message

scan dependency: %w

What it means

scanDependencyRow converts one dependency row into types.Dependency; this error wraps a Scan failure of (issue_id, depends_on_id, type, created_at, created_by, metadata, thread_id). It fires when the dependencies table row shape differs from the expected seven columns or a column type can't convert (NULL in a non-nullable-scanned column, wrong type). Callers getDependencyRecordsIntoFromTable / getAllDependencyRecordsIntoFromTable propagate it.

Source

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

			seen[id] = true
			blocked[id] = b != 0
		}
		_ = rows.Close()
		if err := rows.Err(); err != nil {
			return fmt.Errorf("is_blocked rows from %s: %w", table, err)
		}
	}
	return nil
}

// scanDependencyRow scans a single dependency row from a *sql.Rows.
func scanDependencyRow(rows *sql.Rows) (*types.Dependency, error) {
	var dep types.Dependency
	var createdAt sql.NullTime
	var metadata, threadID sql.NullString

	if err := rows.Scan(&dep.IssueID, &dep.DependsOnID, &dep.Type, &createdAt, &dep.CreatedBy, &metadata, &threadID); err != nil {
		return nil, fmt.Errorf("scan dependency: %w", err)
	}

	if createdAt.Valid {
		dep.CreatedAt = createdAt.Time
	}
	if metadata.Valid {
		dep.Metadata = metadata.String
	}
	if threadID.Valid {
		dep.ThreadID = threadID.String
	}

	return &dep, nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Run `bd doctor` / migrations to restore the expected dependencies schema.
  2. Find and repair offending rows (SELECT rows with NULL issue_id/depends_on_id/type) and delete or fix them.
  3. Re-sync the database (bd dolt pull / re-import) if rows are corrupt.
  4. Match the binary version to the schema version that created the database.

Example fix

// before: schema has 8 columns, Scan expects 7 -> mismatch
if err := rows.Scan(&dep.IssueID, &dep.DependsOnID, &dep.Type, &createdAt, &dep.CreatedBy, &metadata, &threadID); err != nil {
	return nil, fmt.Errorf("scan dependency: %w", err)
}
// after: migrate DB back to expected shape, or widen Scan if a new column is intentional
var extra sql.NullString
if err := rows.Scan(&dep.IssueID, &dep.DependsOnID, &dep.Type, &createdAt, &dep.CreatedBy, &metadata, &threadID, &extra); err != nil {
	return nil, fmt.Errorf("scan dependency: %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

cols, err := dependencyTableColumns(db)
if err != nil { return err }
want := []string{"issue_id", "depends_on_id", "type", "created_at", "created_by", "metadata", "thread_id"}
if !equalCols(cols, want) {
	return fmt.Errorf("dependencies schema drift: got %v want %v", cols, want)
}

Type guard

func isSchemaMismatchErr(err error) bool {
	msg := err.Error()
	return strings.Contains(msg, "sql: expected ") ||
		strings.Contains(msg, "Unknown column") ||
		strings.Contains(msg, "convert")
}

Try / catch

deps, err := getAllDependencyRecordsIntoFromTable(ctx, tx, dest, table)
if err != nil {
	if isSchemaMismatchErr(err) {
		return fmt.Errorf("run `bd doctor`/migrations: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Reading dependency records when the dependencies table schema changed (columns added/removed/reordered) or a column that must be non-NULL (issue_id, depends_on_id, type) is NULL; metadata/thread_id NULLability is handled via sql.NullString, so the failure usually comes from the first three columns or created_at type drift.

Common situations: Version mismatch between beads binary and database schema; manual ALTERs to the dependencies table; corrupted rows where required columns are NULL after a failed import.

Related errors


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