gastownhall/beads · error · issueops.ErrValidation
%w: apply batch item %d: %v
Error message
%w: apply batch item %d: %v
What it means
The edge metadata on a DepAdd item must pass normalizeApplyEdgeMetadata for its type (valid gate metadata shape/content). When normalization fails, the underlying error is wrapped as %w: apply batch item %d: %v with issueops.ErrValidation. The message's %v carries the specific normalization failure.
Source
Thrown at internal/storage/batch_apply.go:274
// as a request a caller could not have composed.
func planApplyBatchDepAdd(item *issueops.DepAddItem, index int, keyIndex map[string]int) error {
if err := validateApplyTargetRef(item.Source, index, "source", keyIndex); err != nil {
return err
}
if err := validateApplyTargetRef(item.Target, index, "target", keyIndex); err != nil {
return err
}
if item.Source == item.Target {
return fmt.Errorf("%w: apply batch item %d: %s cannot depend on itself",
issueops.ErrSelfDependency, index, applyRefLabel(item.Source))
}
if !item.Type.IsValid() {
return fmt.Errorf("%w: apply batch item %d requires a dependency type (max %d chars)",
issueops.ErrValidation, index, types.MaxDependencyTypeLen)
}
metadata, err := normalizeApplyEdgeMetadata(item.Type, item.Metadata)
if err != nil {
return fmt.Errorf("%w: apply batch item %d: %v", issueops.ErrValidation, index, err)
}
item.Metadata = metadata
return nil
}
// checkApplyExpectedVersion refuses a version guard on a row an earlier item of
// this request already mutated.
//
// IT IS A REQUEST-SHAPE RULE, not a race. The token is server-minted and
// rewritten by the write, so mid-request there is no value a caller COULD send:
// the pre-request token is stale by construction, and a row this request just
// created never had one the caller could read. Refusing statically says so;
// letting it through would answer every such request with ErrVersionMismatch
// and leave the caller looking for a concurrent writer that does not exist.
//
// ExpectedStatus and ExpectedAssignee carry no such rule, and the difference is
// that a caller CAN know what its own earlier item set them to.
func checkApplyExpectedVersion(expected *int64, target issueops.Ref, index int, touched map[string]bool) error {View on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped inner error (%v) for the specific normalization failure and fix the Metadata field accordingly
- Omit Metadata (leave nil/empty) if the edge needs no gate
- Build metadata via the library's helpers for the given dependency type instead of hand-crafting maps
Example fix
// before
DepAdd: &issueops.DepAddItem{Source: s, Target: t, Type: "blocks", Metadata: map[string]any{"gates": "bogus"}}
// after
DepAdd: &issueops.DepAddItem{Source: s, Target: t, Type: "blocks"} // or metadata built via the gate helper Defensive patterns
Strategy: validation
Validate before calling
for i, it := range items {
if it.DepAdd == nil || it.DepAdd.Metadata == nil { continue }
if _, err := normalizeApplyEdgeMetadata(it.DepAdd.Type, it.DepAdd.Metadata); err != nil {
return fmt.Errorf("dep item %d: %w", i, err)
}
} Type guard
func edgeMetaValid(e *issueops.DepAddItem) bool {
if e == nil { return false }
if e.Metadata == nil { return true }
_, err := normalizeApplyEdgeMetadata(e.Type, e.Metadata)
return err == nil
} Try / catch
if err := store.PlanApplyBatch(plan); err != nil {
if errors.Is(err, issueops.ErrValidation) {
// the %v suffix carries the specific metadata failure; log it, fix Metadata
}
return err
} Prevention
- Build edge metadata with the library's gate helpers, not raw maps
- Leave Metadata unset for plain edges
- Pin library versions and review metadata-schema changes when upgrading
When it happens
Trigger: PlanApplyBatch with a DepAdd item whose Metadata field violates the rules for its Type (e.g. gate metadata with wrong fields, malformed values, or metadata not permitted for that dependency type).
Common situations: Hand-building gate metadata with wrong key names; copying metadata from a different dependency type that has different rules; library version changes tightening the expected metadata schema.
Related errors
- %w: apply batch item %d has a metadata_ref with an empty key
- %w: apply batch item %d: %s cannot depend on itself
- %w: apply batch item %d requires a dependency type (max %d c
- ExternalDoltConfig: must set Socket or (Host, Port)
- db: DependencySQLRepository.Insert: dep must not be nil
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/5dba285550d4aaa0.
Report an issue: GitHub.