gastownhall/beads · error

create: add waits-for: %w

Error message

create: add waits-for: %w

What it means

Wraps a failure from depRepo.Insert when persisting the waits-for dependency during issue creation. The gate metadata was marshaled successfully but the database insert of the dependency row failed. Causes mirror ordinary dependency inserts: constraint violations, unknown referenced IDs, or storage/driver errors.

Source

Thrown at internal/storage/domain/issue.go:1054

		}
		depSourceIsWisp, err := u.isWispID(ctx, dep.IssueID)
		if err != nil {
			return result, fmt.Errorf("create: determine dep source tier for %s: %w", dep.IssueID, err)
		}
		if err := u.depRepo.Insert(ctx, dep, actor, DepInsertOpts{UseWispsTable: depSourceIsWisp}); err != nil {
			return result, fmt.Errorf("create: add dep %s -> %s: %w", dep.IssueID, dep.DependsOnID, err)
		}
		result.PostCreateWrites = true
	}

	if params.WaitsFor != nil {
		// Spawner identity is the depends_on_id; metadata carries the gate.
		dep, err := types.NewWaitsForDependency(issue.ID, params.WaitsFor.SpawnerID, params.WaitsFor.Gate)
		if err != nil {
			return result, fmt.Errorf("create: marshal waits-for meta: %w", err)
		}
		if err := u.depRepo.Insert(ctx, dep, actor, DepInsertOpts{UseWispsTable: useWisp}); err != nil {
			return result, fmt.Errorf("create: add waits-for: %w", err)
		}
		result.PostCreateWrites = true
	}

	return result, nil
}

func validateExplicitIDPrefix(id, prefix, allowedPrefixes string) error {
	if strings.HasPrefix(id, prefix+"-") {
		return nil
	}
	for _, allowed := range strings.Split(allowedPrefixes, ",") {
		allowed = strings.TrimSpace(allowed)
		if allowed != "" && strings.HasPrefix(id, allowed+"-") {
			return nil
		}
	}
	return fmt.Errorf("%w: issue ID %s does not match configured prefix %s", storage.ErrPrefixMismatch, id, prefix)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Verify the SpawnerID refers to an existing issue
  2. Check the wrapped inner error for the storage-level cause
  3. Confirm wisp/durable tier consistency (useWisp matches both issue and spawner)
  4. Retry transient storage errors; inspect driver health if persistent
Defensive patterns

Strategy: try-catch

Validate before calling

if params.WaitsFor != nil {
    if _, err := uc.GetIssue(ctx, params.WaitsFor.SpawnerID); err != nil {
        return fmt.Errorf("spawner %s must exist before waits-for", params.WaitsFor.SpawnerID)
    }
}

Try / catch

_, err := uc.Create(ctx, params, actor)
if err != nil && strings.Contains(err.Error(), "add waits-for") {
    // inspect wrapped storage cause; retry only on transient errors
    if isTransient(err) { backoffRetry() }
}

Prevention

When it happens

Trigger: Calling Create with params.WaitsFor set where the depRepo.Insert call into the issues (or wisps) deps table fails — invalid spawner ID reference, constraint violation, or DB error.

Common situations: WaitsFor pointing at a spawner ID that doesn't exist or was deleted; transient Dolt/storage failures; wrong storage tier (wisp vs durable) routing mismatch.

Related errors


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