gastownhall/beads · error

touch dependency coordination: unsupported table %q

Error message

touch dependency coordination: unsupported table %q

What it means

TouchDependencyCoordinationTableInTx only accepts exactly two table names — the durable tier ("dependencies") and the ephemeral tier ("wisp_dependencies") — because the coordination key is derived per table. Passing any other table name is rejected as a programming error. This prevents coordination metadata being written for tables that don't participate in dependency freshness tracking.

Source

Thrown at internal/storage/issueops/dependency_coordination.go:38

// issue's incoming parent-child edges use these cells to make concurrent Dolt
// transactions conflict rather than cell-merge.
func touchDependencyCoordinationInTx(ctx context.Context, tx DBTX, parentID string) error {
	for _, tier := range [2]string{dependencyCoordinationDurableTier, dependencyCoordinationEphemeralTier} {
		if err := TouchDependencyCoordinationTableInTx(ctx, tx, parentID, tier); err != nil {
			return err
		}
	}
	return nil
}

// TouchDependencyCoordinationTableInTx rewrites the coordination cell for one
// dependency table. table must be dependencies or wisp_dependencies.
func TouchDependencyCoordinationTableInTx(ctx context.Context, tx DBTX, parentID, table string) error {
	if parentID == "" {
		return fmt.Errorf("touch dependency coordination: parent ID must not be empty")
	}
	if table != dependencyCoordinationDurableTier && table != dependencyCoordinationEphemeralTier {
		return fmt.Errorf("touch dependency coordination: unsupported table %q", table)
	}
	key := dependencyCoordinationKey(parentID, table)
	if _, err := tx.ExecContext(ctx,
		"REPLACE INTO local_metadata (`key`, value) VALUES (?, ?)", key, strconv.FormatInt(FreshRowLock(), 10)); err != nil {
		return fmt.Errorf("touch dependency coordination for %s: %w", table, err)
	}
	return nil
}

func dependencyCoordinationKey(parentID, table string) string {
	shard := dependencyCoordinationShard(parentID)
	// A tier has 4096 shard rows: enough to keep unrelated writes apart while
	// bounding the clone-local coordination state at 8192 rows. Same-parent
	// operations always resolve to the same shard; a hash collision only adds a
	// safe serialization conflict.
	return fmt.Sprintf("%s%s/%s/%03x", dependencyCoordinationKeyPrefix, dependencyCoordinationKeyVersion, table, shard)
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Pass exactly "dependencies" or "wisp_dependencies" (use the dependencyCoordination* tier constants).
  2. Grep for all TouchDependencyCoordinationTableInTx call sites and confirm each table argument.
  3. Centralize table-name selection in a helper that can only return the two valid tiers.

Example fix

// before
touchDependencyCoordinationTableInTx(ctx, tx, parentID, "deps")
// after
touchDependencyCoordinationTableInTx(ctx, tx, parentID, dependencyCoordinationDurableTier) // "dependencies"
Defensive patterns

Strategy: validation

Validate before calling

var validCoordTables = map[string]bool{
    "dependencies": true,
    "wisp_dependencies": true,
}
if !validCoordTables[table] {
    return fmt.Errorf("table %q does not support coordination touch", table)
}
err := TouchDependencyCoordinationTableInTx(ctx, tx, parentID, table)

Type guard

func isCoordinationTable(t string) bool {
    return t == "dependencies" || t == "wisp_dependencies"
}

Try / catch

if err := TouchDependencyCoordinationTableInTx(ctx, tx, parentID, table); err != nil {
    return fmt.Errorf("unsupported coordination table %q: %w", table, err)
}

Prevention

When it happens

Trigger: Calling TouchDependencyCoordinationTableInTx with a table string other than the two recognized dependency tables (typo, wrong constant, or refactoring left an old table name in place).

Common situations: Internal refactors renaming dependency tables without updating touch call sites; writing generic helper code that forwards arbitrary table names; tests exercising the function with placeholder names.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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