gastownhall/beads · error · storage.ErrNotFound

ErrNotFound

ErrNotFound

Error message

create: dependencies could not be created: %s: %w

What it means

ExecuteCreate/ExecuteCreateBatch skip dependencies that cannot be resolved (e.g. the depends-on issue does not exist or is unreachable on the caller's plane) instead of failing the whole batch silently. If any were skipped, the entire create is rolled back and this error, wrapping storage.ErrNotFound, lists each skipped edge as "issueID -> dependsOnID (reason)". The transaction is aborted so the create never partially lands.

Source

Thrown at internal/storage/issueops/execution.go:128

	}
	return publicops.CreateResult{Issue: hydrated}, tables, nil
}

// skippedDependency records an edge the batch engine declined to write.
type skippedDependency struct{ issueID, dependsOnID, reason string }

// skippedDependencyError refuses a guarded create whose requested edges were
// not all written. The batch engine drops a dangling edge so a partial import
// still lands, but a guarded create that reported success while silently
// discarding a parent, waits-for, or explicit dependency is data loss: the
// caller has no way to learn the relationship is missing. Refusing rolls the
// whole create back with the enclosing transaction.
func skippedDependencyError(skipped []skippedDependency) error {
	edges := make([]string, 0, len(skipped))
	for _, edge := range skipped {
		edges = append(edges, fmt.Sprintf("%s -> %s (%s)", edge.issueID, edge.dependsOnID, edge.reason))
	}
	return fmt.Errorf("create: dependencies could not be created: %s: %w", strings.Join(edges, "; "), storage.ErrNotFound)
}

// ExecuteUpdate applies a guarded update in tx and reports durable tables changed.
func ExecuteUpdate(ctx context.Context, tx *sql.Tx, request publicops.UpdateRequest) (publicops.UpdateResult, ChangedTables, error) {
	attempt := CloneUpdateRequest(request)
	if attempt.Actor == "" || attempt.IssueID == "" {
		return publicops.UpdateResult{}, nil, fmt.Errorf("%w: update requires actor and issue ID", storage.ErrValidation)
	}
	if err := ValidateUpdateRequest(attempt); err != nil {
		return publicops.UpdateResult{}, nil, err
	}
	if err := ValidateMetadataPatch(attempt.Patch.Metadata); err != nil {
		return publicops.UpdateResult{}, nil, err
	}
	// The plane restriction is resolved HERE, inside the update's own
	// transaction, so a caller that serves durable issues only cannot be handed
	// a wisp by a resolve that ran earlier.
	if attempt.IssuePlaneOnly && IsActiveWispInTx(ctx, tx, attempt.IssueID) {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the edge list in the message, verify each depends-on ID exists (bd show <id>), and correct or drop the bad IDs.
  2. Create missing dependency issues first, then re-run the create.
  3. If the dependency is a wisp and you require durable issues, recreate it as a durable issue or drop the edge.
  4. Re-run the create; the original transaction was rolled back so nothing was written.

Example fix

// before
bd create "Task" --depends-on=bd-9999 // bd-9999 does not exist
// after
bd show bd-9999 || bd create "Dependency" # then use the real ID
bd create "Task" --depends-on=bd-1000
Defensive patterns

Strategy: validation

Validate before calling

for _, depID := range req.Dependencies {
	if _, err := GetIssueInTx(ctx, tx, depID); err != nil {
		return fmt.Errorf("dependency %s does not exist: %w", depID, err)
	}
}

Try / catch

_, _, err := ExecuteCreateBatch(ctx, tx, batch)
if errors.Is(err, storage.ErrNotFound) && strings.Contains(err.Error(), "dependencies could not be created") {
	skipped := parseSkippedEdges(err.Error()) // "id -> depId (reason)"
	return fmt.Errorf("fix or drop these dependency edges, then retry: %v", skipped)
}

Prevention

When it happens

Trigger: Calling ExecuteCreate or ExecuteCreateBatch with a request whose Dependencies reference issue IDs that do not exist, were closed/deleted, or are wisps invisible to a durable-only plane caller.

Common situations: Typo'd or stale issue IDs in a --depends-on flag; referencing issues living in a different database/remote; batch creates generated from scripts with hard-coded IDs; wisp/durable plane mismatch after switching storage modes.

Related errors


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