gastownhall/beads · error

parsing metadata for %s: %w

Error message

parsing metadata for %s: %w

What it means

The issue's metadata column contains data, but it is not valid JSON or not a JSON object, so json.Unmarshal into map[string]interface{} failed. The library treats metadata as a JSON object of slots; corrupt or unexpected content triggers this wrap with the issue ID.

Source

Thrown at internal/storage/dolt/slots.go:102

	}
	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)
		if err != nil {
			return "", fmt.Errorf("marshaling slot value for %s.%s: %w", issueID, key, err)
		}
		return string(raw), nil
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the issue's metadata column and repair it to a valid JSON object (e.g. UPDATE issues SET metadata='{}' ...).
  2. Re-set all slots with SlotSet to rewrite clean JSON.
  3. If migrating data, sanitize metadata JSON before import.

Example fix

// before
UPDATE issues SET metadata = '{owner: alice}' WHERE id = 'bd-1';  // invalid JSON
// after
UPDATE issues SET metadata = '{"owner": "alice"}' WHERE id = 'bd-1';
Defensive patterns

Strategy: validation

Validate before calling

issue, _ := store.GetIssue(ctx, issueID)
if len(issue.Metadata) > 0 && !json.Valid(issue.Metadata) {
	// repair or reject before calling SlotGet
}

Type guard

func metadataIsJSONObject(raw []byte) bool {
	var m map[string]interface{}
	return len(raw) > 0 && json.Unmarshal(raw, &m) == nil
}

Try / catch

val, err := store.SlotGet(ctx, id, key)
if err != nil && strings.Contains(err.Error(), "parsing metadata") {
	// quarantine the issue's metadata and re-set slots
}

Prevention

When it happens

Trigger: SlotGet on an issue whose metadata blob was written by an older schema version, hand-edited, or corrupted so json.Unmarshal fails.

Common situations: Manual UPDATE of the metadata column with malformed JSON; migration from another tracker leaving non-object JSON (e.g. a bare string or array); partial write from a crashed older version.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/4cd0ca52cb901381. Report an issue: GitHub.