gastownhall/beads · error · issueops.ErrValidation
%w: apply batch item %d requires a dependency type (max %d c
Error message
%w: apply batch item %d requires a dependency type (max %d chars)
What it means
Every DepAdd item requires a dependency Type that passes IsValid() (non-empty and within types.MaxDependencyTypeLen characters). This error fires when the type is missing, empty, or too long. Wraps issueops.ErrValidation.
Source
Thrown at internal/storage/batch_apply.go:269
// request has already REWRITTEN, and an edge write is a change to the graph
// rather than to either endpoint's row: the role promises nothing about whether
// it moves the source's version token. A later guard on that source is
// therefore left to the substrate, where a genuine mismatch is
// ErrVersionMismatch — an honest refusal — rather than being refused up front
// 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 ErrVersionMismatchView on GitHub (pinned to 71377f2769)
Solutions
- Set a valid dependency type (e.g. "blocks", "related") on the DepAdd item
- Truncate or normalize long type values to MaxDependencyTypeLen before batching
- Validate the type at edge-generation time and skip/fix invalid rows
Example fix
// before
item := issueops.ApplyItem{Kind: issueops.ItemDepAdd, DepAdd: &issueops.DepAddItem{Source: s, Target: t}}
// after
item := issueops.ApplyItem{Kind: issueops.ItemDepAdd, DepAdd: &issueops.DepAddItem{Source: s, Target: t, Type: "blocks"}} Defensive patterns
Strategy: validation
Validate before calling
for i, it := range items {
if it.DepAdd == nil { continue }
if !it.DepAdd.Type.IsValid() {
return fmt.Errorf("dep item %d has invalid type %q (max %d chars)", i, it.DepAdd.Type, types.MaxDependencyTypeLen)
}
} Type guard
func hasValidDepType(e *issueops.DepAddItem) bool {
return e != nil && e.Type.IsValid()
} Try / catch
if err := store.PlanApplyBatch(plan); err != nil {
if errors.Is(err, issueops.ErrValidation) && strings.Contains(err.Error(), "requires a dependency type") {
// set or fix the Type field and rebuild the plan
}
return err
} Prevention
- Always set Type when constructing DepAdd items — use a helper
- Validate Type.IsValid() at edge-generation time
- Enforce the MaxDependencyTypeLen limit in input sanitization
When it happens
Trigger: PlanApplyBatch with DepAdd{Source: ..., Target: ..., Type: ""} or a Type longer than types.MaxDependencyTypeLen; types like "blocks" are valid, empty or oversized strings are not.
Common situations: Forgetting to set Type when constructing DepAdd structs; copying edge data from an export where the type column was blank; a type string that grew past the max length after data changes.
Related errors
- %w: apply batch item %d: %s cannot depend on itself
- %w: apply batch item %d: %v
- db: DependencySQLRepository.Insert: dep must not be nil
- db: DependencySQLRepository.Insert: IssueID must not be empt
- db: DependencySQLRepository.Insert: DependsOnID must not be
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/0ee2457d09101f1f.
Report an issue: GitHub.