gastownhall/beads · error
serializing waits-for also_blocks metadata: %w
Error message
serializing waits-for also_blocks metadata: %w
What it means
After adding also_blocks=true to WaitsForMeta, NewWaitsForBlockingDependency re-serializes the struct with json.Marshal; a marshal error is wrapped with this message and returned.
Source
Thrown at internal/types/types.go:1434
// metadata so waitsForGateBlockedSQL additionally blocks while the spawner
// itself is open, not only while it has an open parent-child child. Use this
// instead of NewWaitsForDependency exactly when the caller is collapsing a
// would-be DepBlocks edge (from needs/depends_on) into this waits-for edge
// because the two would otherwise collide on the same (source, target) pair
// — never for a plain waits_for with no matching needs/depends_on entry.
func NewWaitsForBlockingDependency(issueID, spawnerID, gate string) (*Dependency, error) {
dep, err := NewWaitsForDependency(issueID, spawnerID, gate)
if err != nil {
return nil, err
}
var meta WaitsForMeta
if err := json.Unmarshal([]byte(dep.Metadata), &meta); err != nil {
return nil, fmt.Errorf("parsing waits-for metadata to set also_blocks: %w", err)
}
meta.AlsoBlocks = true
raw, err := json.Marshal(meta)
if err != nil {
return nil, fmt.Errorf("serializing waits-for also_blocks metadata: %w", err)
}
dep.Metadata = string(raw)
return dep, nil
}
// NewGraphNodeDependency builds the dependency record for a graph-plan node's
// inline dep, shared by the embedded and domain apply paths so their
// resolution semantics cannot drift: an empty type defaults to blocks, and
// the target resolves as a plan-local key first, then as a literal issue ID.
// Waits-for deps carry gate metadata like waits-for edges (all-children
// default, no explicit spawner).
func NewGraphNodeDependency(issueID string, depType DependencyType, target string, keyToID map[string]string) (*Dependency, error) {
if depType == "" {
depType = DepBlocks
}
targetID := keyToID[target]
if targetID == "" {
targetID = targetView on GitHub (pinned to 71377f2769)
Solutions
- Rebuild the binary to rule out a patched types package
- Check for a custom MarshalJSON on WaitsForMeta and remove it
- File an upstream issue with the inner wrapped error if it reproduces on a stock build
Defensive patterns
Strategy: try-catch
Try / catch
dep, err := types.NewWaitsForBlockingDependency(issueID, spawnerID, gate)
if err != nil {
if strings.Contains(err.Error(), "serializing waits-for also_blocks") {
log.Fatalf("also_blocks metadata serialization failed: %v", err)
}
return err
} Prevention
- Avoid custom marshalers on WaitsForMeta
- Use a stock build; rebuild if this fires unexpectedly
When it happens
Trigger: json.Marshal(meta) failing after meta.AlsoBlocks was set to true inside NewWaitsForBlockingDependency.
Common situations: Theoretically unreachable: WaitsForMeta holds only string and bool fields which always marshal successfully; would imply a non-standard build or custom marshaler.
Related errors
- serializing waits-for metadata: %w
- failed to marshal backup state: %w
- failed to marshal issue %s: %w
- failed to marshal interactions log entry: %w
- marshal create request: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/6b84df75f9015296.
Report an issue: GitHub.