gastownhall/beads · error

proxied-server provider %T does not offer the import surface

Error message

proxied-server provider %T does not offer the import surface

What it means

In proxied-server mode, import goes through a provider object that must implement the uow.ImporterSource interface; proxiedImporter type-asserts it and errors if the concrete provider type lacks the import surface. This is an internal wiring/compatibility defect, not user input.

Source

Thrown at cmd/bd/import_proxied_server.go:26

	"github.com/steveyegge/beads/internal/config"
	"github.com/steveyegge/beads/internal/storage/uow"
	"github.com/steveyegge/beads/internal/types"
	publicops "github.com/steveyegge/beads/issueops"
)

// proxiedImporter hands back the guarded bulk-import surface for the
// proxied-server provider, through the provider's OWN capability accessor —
// the same two-step proxiedIssueReader and proxiedBatchCloser perform, and
// for the same reason: the accessor is where each layer is added, so a
// command that reached for the constructor would get an unlayered importer.
func proxiedImporter() (publicops.Importer, error) {
	if uowProvider == nil {
		return nil, errors.New("proxied-server UOW provider not initialized")
	}
	src, ok := uowProvider.(uow.ImporterSource)
	if !ok {
		return nil, fmt.Errorf("proxied-server provider %T does not offer the import surface", uowProvider)
	}
	return src.Importer()
}

// runImportRecordsProxied is the proxied-server import pipeline over the
// parsed records. It mirrors runImportRecordsClassic stage for stage — dedup,
// dry-run classification, stale pre-filter, batch write, issue_prefix
// reconciliation — through the SAME classification and reporting code, with
// two deliberate structural differences:
//
//   - ONE COMMIT PER INVOCATION. The classic path chunks a large import into
//     bounded transactions (a SQLite write-lock fairness measure) and commits
//     the issue_prefix sync separately; the proxied path has no PostRun
//     auto-commit and the whole import — rows, memories, prefix sync — lands
//     in ONE unit of work with ONE history entry, the Importer capability's
//     contract.
//
//   - The stale guard keeps its classic two-half shape: the pre-filter runs in

View on GitHub (pinned to 71377f2769)

Solutions

  1. Upgrade the bd binary (and any plugins) so server and client versions match and the provider implements the import surface
  2. Bypass the proxied backend: unset the proxied-server routing/env so the classic embedded import path runs
  3. Check how uowProvider is initialized; if custom, implement uow.ImporterSource and return a real publicops.Importer
  4. File/report the %T type in the message to maintainers — it identifies the non-conforming provider

Example fix

// before
provider := myMinimalProvider{}        // lacks Importer()
uowProvider = provider
// after
provider := publicops.NewUOWProvider() // implements uow.ImporterSource
uowProvider = provider
Defensive patterns

Strategy: fallback

Validate before calling

bd --version   # ensure server and client versions match
bd import --help >/dev/null   # binary actually has the import surface

Try / catch

if ! bd import data.jsonl 2>err.log; then
  grep 'does not offer the import surface' err.log && bd import data.jsonl   # after unsetting proxied-server routing
fi

Prevention

When it happens

Trigger: Running `bd import` while using the proxied-server backend (usesProxiedServer() true) with a uowProvider build/wiring that does not implement uow.ImporterSource — typically a version-skew binary, plugin, or misconstructed provider injected at startup.

Common situations: Mixed-version bd binaries/plugins where the server provider predates the import surface; custom or test providers substituted for the real one; env routing (proxied server flags) pointing import at an incompatible backend.

Related errors


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