gastownhall/beads · error
no slot %q on %s: no metadata
Error message
no slot %q on %s: no metadata
What it means
SlotGet found the issue but its metadata column is empty (zero-length JSON), so no slot key can exist on it. This is a deliberately descriptive 'not found' error telling you the issue has no metadata map at all, as opposed to having metadata without the requested key.
Source
Thrown at internal/storage/dolt/slots.go:97
// byte-compatible with the historical whole-metadata rewrite.
func (s *DoltStore) SlotSet(ctx context.Context, issueID, key, value, actor string) error {
raw, err := json.Marshal(value)
if err != nil {
return fmt.Errorf("marshaling slot value for %s.%s: %w", issueID, key, err)
}
return s.MergeMetadata(ctx, issueID, key, raw, actor)
}
// SlotGet retrieves the value of a metadata key from an issue.
// Returns an error if the issue has no metadata or the key is not found.
func (s *DoltStore) SlotGet(ctx context.Context, issueID, key string) (string, error) {
issue, err := s.GetIssue(ctx, issueID)
if err != nil {
return "", fmt.Errorf("getting issue %s: %w", issueID, err)
}
if len(issue.Metadata) == 0 {
return "", fmt.Errorf("no slot %q on %s: no metadata", key, issueID)
}
metadata := make(map[string]interface{})
if err := json.Unmarshal(issue.Metadata, &metadata); err != nil {
return "", fmt.Errorf("parsing metadata for %s: %w", issueID, err)
}
val, ok := metadata[key]
if !ok {
return "", fmt.Errorf("no slot %q on %s: key not found", key, issueID)
}
switch v := val.(type) {
case string:
return v, nil
default:
// Non-string values are returned as JSON
raw, err := json.Marshal(v)View on GitHub (pinned to 71377f2769)
Solutions
- Call SlotSet/MergeMetadata to create the slot before reading it.
- Treat this as a miss and provide a default value in the caller instead of erroring.
- Check with bd or the metadata column whether the issue was expected to carry metadata.
Example fix
// before
val, err := store.SlotGet(ctx, id, "owner")
if err != nil {
return err
}
// after
val, err := store.SlotGet(ctx, id, "owner")
if err != nil && strings.Contains(err.Error(), "no slot") {
val = "unassigned" // default when the issue has no metadata
} Defensive patterns
Strategy: fallback
Validate before calling
issue, err := store.GetIssue(ctx, issueID)
if err == nil && len(issue.Metadata) == 0 {
// no metadata; skip SlotGet and use a default
} Try / catch
val, err := store.SlotGet(ctx, id, key)
if err != nil && strings.Contains(err.Error(), "no metadata") {
val = defaultValue
} Prevention
- Initialize required slots with SlotSet at issue creation time.
- Treat missing metadata as an expected miss and code a default path.
- Distinguish this from the key-not-found case by the 'no metadata' suffix.
When it happens
Trigger: Calling SlotGet on an issue that was never given any metadata (no SlotSet/MergeMetadata ever called on it).
Common situations: Reading a slot before ever setting it; querying an old issue created before the slot feature was used; assuming SlotSet ran when it actually failed earlier.
Related errors
- no slot %q on %s: key not found
- record repo_id: %w
- record clone_id: %w
- record last_import_time: %w
- getting issue %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/08eccc6d3df75145.
Report an issue: GitHub.