gastownhall/beads · error
edge %d: invalid dependency type %q
Error message
edge %d: invalid dependency type %q
What it means
`bd graph apply` validates each edge's dependency type against the known DependencyType enum. If edge.type is non-empty but is not a valid dependency type, the plan is rejected with this error so invalid dependency semantics never reach storage.
Source
Thrown at cmd/bd/graph_apply.go:608
}
for i, edge := range plan.Edges {
if edge.FromKey != "" && !seenKeys[edge.FromKey] {
return fmt.Errorf("edge %d: from key %q not found in plan", i, edge.FromKey)
}
if edge.ToKey != "" && !seenKeys[edge.ToKey] {
return fmt.Errorf("edge %d: to key %q not found in plan", i, edge.ToKey)
}
if edge.FromKey == "" && edge.FromID == "" {
return fmt.Errorf("edge %d: must specify from_key or from_id", i)
}
if edge.ToKey == "" && edge.ToID == "" {
return fmt.Errorf("edge %d: must specify to_key or to_id", i)
}
if edge.Type != "" {
dt := types.DependencyType(edge.Type)
if !dt.IsValid() {
return fmt.Errorf("edge %d: invalid dependency type %q", i, edge.Type)
}
}
if edge.Gate != "" || edge.SpawnerKey != "" || edge.SpawnerID != "" {
if graphApplyDependencyType(edge.Type) != types.DepWaitsFor {
return fmt.Errorf("edge %d: gate/spawner fields require type %q", i, types.DepWaitsFor)
}
if edge.Gate != "" && !types.IsValidWaitsForGate(edge.Gate) {
return fmt.Errorf("edge %d: invalid gate %q (valid: %s, %s)", i, edge.Gate, types.WaitsForAllChildren, types.WaitsForAnyChildren)
}
if edge.SpawnerKey != "" && edge.SpawnerID != "" {
return fmt.Errorf("edge %d: cannot specify both spawner_key and spawner_id", i)
}
if edge.SpawnerKey != "" && !seenKeys[edge.SpawnerKey] {
return fmt.Errorf("edge %d: spawner key %q not found in plan", i, edge.SpawnerKey)
}
// Gate evaluation reads the spawner from the dependency target
// (depends_on_id), not metadata, so the spawner must equal the to
// endpoint. Since to_id overrides to_key at apply timeView on GitHub (pinned to 71377f2769)
Solutions
- Check `bd dep types` (or docs) for the exact valid dependency type names and correct edge.type
- Remove edge.type entirely if the default type is acceptable
- Re-generate the plan from the source tool with corrected type names
Example fix
// before
{"from_key": "a", "to_key": "b", "type": "blocks"}
// after
{"from_key": "a", "to_key": "b", "type": "blocks"} (use a valid type, e.g. "blocks" / "related" / "discovered-from") Defensive patterns
Strategy: validation
Validate before calling
valid := map[string]bool{"blocks":true,"related":true,"parent-child":true,"discovered-from":true,"waits-for":true} // check bd dep types for exact list
if e.Type != "" && !valid[e.Type] { return fmt.Errorf("edge type %q invalid", e.Type) } Type guard
func validDepType(t string) bool { return t == "" || types.DependencyType(t).IsValid() } Prevention
- Copy type names from documentation, never from memory
- Centralize type constants in your plan generator
- Lint plans for known enum fields before apply
When it happens
Trigger: An edge in a graph plan has a type string that is not one of the valid dependency types (e.g. "depends" instead of "discovers-from", misspelling, wrong casing).
Common situations: Typo in plan type field; copying a type name from another issue tracker; generating plans with stale type names after a vocabulary change.
Related errors
- invalid graph plan: %w
- edge %d: must specify to_key or to_id
- edge %d: gate/spawner fields require type %q
- node %q: %w
- %w: add dependencies edge %d requires a dependency type (max
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/5d79a1798693db10.
Report an issue: GitHub.