gastownhall/beads · error

proxied-server provider %T does not offer the issue-lifecycl

Error message

proxied-server provider %T does not offer the issue-lifecycle surface

What it means

On the proxied-server route, commands reach storage through a unit-of-work provider. proxiedIssueLifecycle requires that provider to also implement uow.IssueLifecycleSource; when the concrete provider type does not, the issue-lifecycle operations (create/reopen/update via issueops.Lifecycle) cannot proceed and this error names the actual provider type to aid diagnosis.

Source

Thrown at cmd/bd/update_proxied_server.go:78

	if jsonOut && len(updated) > 0 {
		_ = outputJSON(updated)
	}
	if len(failures) > 0 {
		return reportUpdateFailures(failures, len(args))
	}
	return nil
}

// proxiedIssueLifecycle asks the unit-of-work provider for the write role, the
// same way proxiedIssueReader asks it for the read one.
func proxiedIssueLifecycle() (issueops.Lifecycle, error) {
	if uowProvider == nil {
		return nil, errors.New("proxied-server UOW provider not initialized")
	}
	src, ok := uowProvider.(uow.IssueLifecycleSource)
	if !ok {
		return nil, fmt.Errorf("proxied-server provider %T does not offer the issue-lifecycle surface", uowProvider)
	}
	return src.IssueLifecycle()
}

// applyUpdateProxiedOne applies one issue's update — plain or --claim —
// through issueops.Lifecycle. What stays here is this surface's own protocol:
// the template guard, the advisory reassign pre-read, the per-id failure
// taxonomy the multi-id batch needs and the notes-overwrite warning. Hooks are
// NOT among them: they fire from the write plumbing now (the notifying provider
// wired in main.go), which is what makes an update fire the same events here as
// it does on the embedded path.
//
// Provenance carries the commit message this path has always written, so `bd
// dolt log` reads the same after the move as before it. The plane is
// deliberately NOT restricted: `bd update` has always resolved a wisp id,
// unlike the HTTP claim endpoint, which serves durable issues only.
//
// The pre-read is a read of its own, one transaction earlier than the

View on GitHub (pinned to 71377f2769)

Solutions

  1. Upgrade the proxied server to a build whose provider implements IssueLifecycleSource
  2. Check server/provider configuration and restart the proxied server
  3. Report the provider type (%T in the message) if it looks like a wiring bug
Defensive patterns

Strategy: type-guard

Validate before calling

if _, ok := uowProvider.(uow.IssueLifecycleSource); !ok {
    return fmt.Errorf("provider %T lacks IssueLifecycleSource; upgrade server", uowProvider)
}

Type guard

src, ok := uowProvider.(uow.IssueLifecycleSource)
if !ok {
    return nil, fmt.Errorf("provider %T does not offer the issue-lifecycle surface", uowProvider)
}
return src.IssueLifecycle()

Try / catch

if err := runUpdate(); err != nil {
    if strings.Contains(err.Error(), "does not offer the issue-lifecycle surface") {
        // fall back to direct (non-proxied) route or surface an upgrade hint
    }
}

Prevention

When it happens

Trigger: Running create/reopen/update against a proxied server whose configured uowProvider lacks the IssueLifecycleSource interface — typically a mismatched or partially initialized server build/provider wiring.

Common situations: Version mismatch between bd client and proxied server; custom or stub provider injected in tests/embedded setups; server started with a provider that only implements a narrower surface.

Related errors


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