gastownhall/beads · error
getting issue %s: %w
Error message
getting issue %s: %w
What it means
SlotGet failed while fetching the underlying issue before reading its metadata slot. The original error from GetIssue (issue not found, DB connection failure, query error, etc.) is wrapped with the issue ID so the caller knows which record failed. This is a wrapper error: the root cause is the embedded %w error.
Source
Thrown at internal/storage/dolt/slots.go:93
//
// Built on MergeMetadata so the read-modify-write is atomic: two concurrent
// SlotSet calls on different keys both survive. The string value is stored as a
// JSON string (json.Marshal(value) yields "value"), keeping the stored metadata
// 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:View on GitHub (pinned to 71377f2769)
Solutions
- Verify the issue ID exists (e.g. bd show <id> or query the issues table) before calling SlotGet.
- Inspect the wrapped cause via errors.Unwrap / errors.Is to distinguish 'not found' from connection failures.
- Confirm the Dolt database is reachable and the correct branch is checked out (bd doctor).
Example fix
// before
val, err := store.SlotGet(ctx, id, key)
if err != nil {
return err // ambiguous root cause
}
// after
val, err := store.SlotGet(ctx, id, key)
if err != nil {
if errors.Is(err, storage.ErrNotFound) {
return fmt.Errorf("issue %s not found", id)
}
return err
} Defensive patterns
Strategy: try-catch
Validate before calling
if _, err := store.GetIssue(ctx, issueID); err != nil {
// issue missing or DB down; skip SlotGet
return err
} Type guard
func isNotFound(err error) bool {
return errors.Is(err, storage.ErrNotFound)
} Try / catch
val, err := store.SlotGet(ctx, id, key)
if err != nil {
var inner error
if errors.As(err, &inner) && errors.Is(inner, storage.ErrNotFound) {
// handle missing issue
}
return err
} Prevention
- Resolve issue IDs from the store itself rather than accepting free-form strings.
- Check errors.Is on the unwrapped cause instead of string matching.
- Ensure the Dolt DB is healthy (bd doctor) before batch slot reads.
When it happens
Trigger: Calling DoltStore.SlotGet(ctx, issueID, key) when GetIssue fails — most commonly the issue ID does not exist, the database is unreachable, or the underlying SQL query fails.
Common situations: Typo'd or stale issue ID passed to SlotGet; issue was deleted between ID capture and the slot read; embedded Dolt server not running; wrong --db path so the issues table is empty.
Related errors
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/7a2b55584e260785.
Report an issue: GitHub.