gastownhall/beads · error

waits-for metadata is not a well-formed gate object: %w

Error message

waits-for metadata is not a well-formed gate object: %w

What it means

For waits-for dependencies, edge metadata must unmarshal into types.WaitsForMeta (a gate object). This error wraps the json.Unmarshal failure, meaning the metadata is syntactically broken or not a JSON object shape compatible with WaitsForMeta.

Source

Thrown at internal/storage/batch_apply.go:377

//
// Every other edge type's metadata is passed through unchanged, checked only
// for being well-formed JSON when it is present at all: the blob is
// type-specific and this role does not know the types.
func normalizeApplyEdgeMetadata(depType types.DependencyType, metadata string) (string, error) {
	trimmed := strings.TrimSpace(metadata)
	if depType != types.DepWaitsFor {
		if trimmed == "" {
			return "", nil
		}
		if !json.Valid([]byte(trimmed)) {
			return "", fmt.Errorf("edge metadata is not well-formed JSON")
		}
		return metadata, nil
	}
	meta := types.WaitsForMeta{}
	if trimmed != "" && trimmed != "{}" {
		if err := json.Unmarshal([]byte(trimmed), &meta); err != nil {
			return "", fmt.Errorf("waits-for metadata is not a well-formed gate object: %w", err)
		}
	}
	if meta.Gate == "" {
		meta.Gate = types.WaitsForAllChildren
	}
	if !types.IsValidWaitsForGate(meta.Gate) {
		return "", fmt.Errorf("waits-for gate %q is neither %q nor %q",
			meta.Gate, types.WaitsForAllChildren, types.WaitsForAnyChildren)
	}
	raw, err := json.Marshal(meta)
	if err != nil {
		return "", fmt.Errorf("serializing waits-for metadata: %w", err)
	}
	return string(raw), nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Construct a types.WaitsForMeta value and json.Marshal it instead of hand-writing the string
  2. Ensure metadata is a JSON object with the expected gate field
  3. Validate the JSON with json.Valid and unmarshal into WaitsForMeta locally first

Example fix

// before
meta := "all-children"
// after
raw, _ := json.Marshal(types.WaitsForMeta{Gate: types.WaitsForAllChildren})
meta := string(raw)
Defensive patterns

Strategy: validation

Validate before calling

var m types.WaitsForMeta
if err := json.Unmarshal([]byte(meta), &m); err != nil {
	return fmt.Errorf("bad waits-for metadata: %w", err)
}

Try / catch

if err != nil && strings.Contains(err.Error(), "waits-for metadata is not a well-formed gate object") {
	// re-encode metadata from types.WaitsForMeta and retry
}

Prevention

When it happens

Trigger: Adding a waits-for dependency whose metadata string fails json.Unmarshal into WaitsForMeta — malformed JSON, or a JSON array/string/number instead of an object.

Common situations: Passing "[\"gate\"]" or a bare quoted string as metadata; forgetting to serialize a WaitsForMeta struct before storing; older metadata formats that no longer match the WaitsForMeta schema.

Related errors


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