gastownhall/beads · error

reading dependencies rows for migration 0053 id backfill: %w

Error message

reading dependencies rows for migration 0053 id backfill: %w

What it means

This wraps failure of the QueryContext that selects dependencies rows with id IS NULL for the migration-0053 backfill. The query failed before any row was returned — connection, SQL, or privilege problem — so the repair cannot collect the edges needing IDs. It is distinct from per-row scan failures.

Source

Thrown at internal/storage/schema/migration_repairs.go:460

	return ensureDependenciesIDPrimaryKey(ctx, db)
}

// backfillDependenciesID fills in any dependencies.id still NULL with
// depid.New(issue_id, target) -- the same deterministic id every insert path
// and the post-migration rekeyDependencyIDs pass use (dep_id_backfill.go) --
// so rows with real edges get a real, cross-clone-stable id rather than a
// throwaway placeholder, and rekeyDependencyIDs finds nothing left to correct
// afterwards. The `WHERE id IS NULL` scope (rather than every row) is what
// makes re-entry after a partial prior run cheap and idempotent: a row this
// function already backfilled, or one that already had an id, is untouched.
func backfillDependenciesID(ctx context.Context, db DBConn) error {
	rows, err := db.QueryContext(ctx, `
		SELECT issue_id, depends_on_issue_id, depends_on_wisp_id, depends_on_external
		FROM dependencies
		WHERE id IS NULL
	`)
	if err != nil {
		return fmt.Errorf("reading dependencies rows for migration 0053 id backfill: %w", err)
	}
	type edge struct {
		issueID                                              string
		dependsOnIssueID, dependsOnWispID, dependsOnExternal sql.NullString
	}
	var edges []edge
	for rows.Next() {
		var e edge
		if err := rows.Scan(&e.issueID, &e.dependsOnIssueID, &e.dependsOnWispID, &e.dependsOnExternal); err != nil {
			_ = rows.Close()
			return fmt.Errorf("scanning dependencies row for migration 0053 id backfill: %w", err)
		}
		edges = append(edges, e)
	}
	if err := rows.Err(); err != nil {
		return fmt.Errorf("iterating dependencies rows for migration 0053 id backfill: %w", err)
	}
	_ = rows.Close()

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check the wrapped driver error and restore connectivity/privileges
  2. Verify the dependencies table exists and is queryable with the app credentials
  3. Re-run the repair; the id check and backfill are idempotent
  4. If the server rejects the SQL, confirm server version compatibility
Defensive patterns

Strategy: try-catch

Validate before calling

// confirm dependencies is readable before the backfill
var n int
if err := db.QueryRowContext(ctx, "SELECT COUNT(*) FROM dependencies").Scan(&n); err != nil {
    return fmt.Errorf("dependencies unreadable, fix before repair: %w", err)
}

Try / catch

if err := repairV53RigAndSplitTargets(ctx, db); err != nil {
    if strings.Contains(err.Error(), "reading dependencies rows for migration 0053") {
        var drv *mysql.MySQLError
        if errors.As(err, &drv) && (drv.Number == 2006 || drv.Number == 2013) {
            db = reconnect(db)
            return repairV53RigAndSplitTargets(ctx, db)
        }
    }
    return err
}

Prevention

When it happens

Trigger: ensureDependenciesIDColumn added dependencies.id (or found it present), then backfillDependenciesID's SELECT ... WHERE id IS NULL errors: connection dropped, dependencies table unreadable/missing, syntax-level failure from an incompatible server, or SELECT privilege denied.

Common situations: Database restart mid-repair; repair user lacking SELECT on dependencies; running against a server version that chokes on the query; table dropped/corrupted between migration steps.

Related errors


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