gastownhall/beads · error

loading proto %s: %w

Error message

loading proto %s: %w

What it means

After successfully resolving the proto argument to an issue ID, bd mol pour loads the full issue with GetIssue before treating it as a template. This error wraps any failure of that fetch, preserving the cause. Unlike the 'not found as formula or proto' error, the ID resolved but the load failed — usually a storage-level problem or a race where the issue vanished between resolve and load.

Source

Thrown at cmd/bd/mol_proxied_server.go:65

		// instead of falling through to the proto-ID lookup below, which
		// would otherwise mask this as "not found as formula or proto ID".
		return HandleError("%v", err)
	}

	res, err := uow.RunTxResult(ctx, uowProvider, func(ctx context.Context, uw uow.UnitOfWork) (pourProxiedResult, string, error) {
		w := newUOWMolWriter(uw)

		subgraph := formulaSubgraph
		protoID := formulaProtoID
		if subgraph == nil {
			resolvedID, err := utils.ResolvePartialID(ctx, w, in.protoArg)
			if err != nil {
				return pourProxiedResult{}, "", fmt.Errorf("%s not found as formula or proto ID", in.protoArg)
			}
			protoID = resolvedID
			protoIssue, err := w.GetIssue(ctx, protoID)
			if err != nil {
				return pourProxiedResult{}, "", fmt.Errorf("loading proto %s: %w", protoID, err)
			}
			if !isProto(protoIssue) {
				return pourProxiedResult{}, "", fmt.Errorf("%s is not a proto (missing '%s' label)", protoID, MoleculeLabel)
			}
			subgraph, err = loadTemplateSubgraph(ctx, w, protoID)
			if err != nil {
				return pourProxiedResult{}, "", fmt.Errorf("loading proto: %w", err)
			}
		}

		type attachmentInfo struct {
			id       string
			issue    *types.Issue
			subgraph *TemplateSubgraph
		}
		var attachments []attachmentInfo
		for _, attachArg := range in.attachArgs {
			attachID, err := utils.ResolvePartialID(ctx, w, attachArg)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Re-run the pour command — a transient lock or race usually resolves
  2. Verify the proto still exists with bd show <protoID>
  3. Check for concurrent bd processes holding the database lock and wait/retry
  4. If the proto is ephemeral/wisp-only, create it as a persistent (non-wisp) issue

Example fix

// before: race-prone sequence inside one tx fallback
protoID, _ := utils.ResolvePartialID(ctx, w, arg)
protoIssue, err := w.GetIssue(ctx, protoID)
// after: retry transient failures
protoIssue, err := w.GetIssue(ctx, protoID)
if err != nil {
	if isTransient(err) { return retry(pour, arg) }
	return fmt.Errorf("loading proto %s: %w", protoID, err)
}
Defensive patterns

Strategy: retry

Validate before calling

// verify the resolved proto is loadable before pouring
protoID, _ := utils.ResolvePartialID(ctx, reader, protoArg)
if _, err := reader.GetIssue(ctx, protoID); err != nil {
	return fmt.Errorf("proto %s cannot be loaded right now", protoID)
}

Try / catch

err := pourCmd(protoArg)
if err != nil && strings.HasPrefix(err.Error(), "loading proto ") {
	time.Sleep(time.Second) // transient storage/race — retry
	err = pourCmd(protoArg)
}

Prevention

When it happens

Trigger: Calling `bd mol pour <protoID>` where ResolvePartialID succeeds but the subsequent GetIssue fails: concurrent deletion of the issue, database lock/corruption, context timeout, or wisp-only issues not visible through the normal GetIssue path.

Common situations: Another agent/process deleted the proto between resolution and load; Dolt database locked by a concurrent bd command; running on an ephemeral (wisp) proto that GetIssue cannot read.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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