gastownhall/beads · error
failed to encode slot metadata: %w
Error message
failed to encode slot metadata: %w
What it means
This error wraps a failure to JSON-serialize the merge slot's metadata (holder + waiters list) via encodeSlotMeta while adding a waiter inside MergeSlotAcquireImpl. The slot state lives in the issue's Metadata field, so if json.Marshal fails the waiter cannot be registered and the acquire transaction aborts. In practice this is nearly impossible since slotMeta only contains a string and a []string.
Source
Thrown at internal/storage/merge_slot.go:118
meta := parseSlotMeta(slot)
result.Holder = meta.Holder
if slot.Status != types.StatusOpen {
// Slot is held.
if wait {
alreadyWaiting := false
for _, w := range meta.Waiters {
if w == holder {
alreadyWaiting = true
break
}
}
if !alreadyWaiting {
meta.Waiters = append(meta.Waiters, holder)
}
metaStr, err := encodeSlotMeta(meta)
if err != nil {
return fmt.Errorf("failed to encode slot metadata: %w", err)
}
if err := tx.UpdateIssue(ctx, slot.ID, map[string]interface{}{"metadata": metaStr}, actor); err != nil {
return fmt.Errorf("failed to add to waiters: %w", err)
}
result.Waiting = true
result.Position = len(meta.Waiters)
}
return nil
}
// Slot is available — acquire it atomically.
newMeta := slotMeta{Holder: holder, Waiters: meta.Waiters}
metaStr, err := encodeSlotMeta(newMeta)
if err != nil {
return fmt.Errorf("failed to encode slot metadata: %w", err)
}
if err := tx.UpdateIssue(ctx, slot.ID, map[string]interface{}{
"status": types.StatusInProgress,View on GitHub (pinned to 71377f2769)
Solutions
- Retry the acquire — the failure is transient/infrastructural, not data-related
- Check that the slot bead's metadata is well-formed JSON via bd show <slot-id>
- If reproducible, report a bug: json.Marshal of slotMeta should never fail
Defensive patterns
Strategy: retry
Validate before calling
meta := slotMeta{Holder: h, Waiters: ws}
if _, err := json.Marshal(meta); err != nil { return fmt.Errorf("slot meta unmarshalable: %w", err) } Try / catch
for i := 0; i < 3; i++ {
res, err := store.MergeSlotAcquire(ctx, holder, actor, true)
if err == nil || !strings.Contains(err.Error(), "failed to encode slot metadata") { break }
time.Sleep(backoff(i))
} Prevention
- Keep slotMeta limited to JSON-marshalable fields (string, []string)
- Treat any occurrence as a bug and file it — json.Marshal of this struct should never fail
- Log the wrapped error (%w) to capture the root marshal cause
When it happens
Trigger: Calling MergeSlotAcquire with wait=true while the slot is held causes the code to append the holder to meta.Waiters and call encodeSlotMeta; the error fires only if json.Marshal of slotMeta fails (e.g. a custom-marshaled corrupted meta or an unmarshalable value injected via MarshalJSON in future changes).
Common situations: Practically never hit by users of the library; seen only during development when the slotMeta struct gains unmarshalable fields or when store metadata is corrupted by a version mismatch.
Related errors
- failed to add to waiters: %w
- failed to acquire slot: %w
- merge slot not found: %s
- no store is open for this workspace
- not found
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/7a27505a9f1243af.
Report an issue: GitHub.