gastownhall/beads · error

proxied-server provider %T does not offer the issue-count su

Error message

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

What it means

The proxied-server path resolves an issue Counter through the global uowProvider's capability accessor. The provider must implement the uow.CounterSource interface; if the concrete provider type wired in at startup doesn't offer that surface, proxiedCounter refuses with this type-mismatch message naming the offending concrete type (%T). It's a wiring/capability bug, not a runtime data problem.

Source

Thrown at cmd/bd/count_proxied_server.go:21

import (
	"errors"
	"fmt"

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

// proxiedCounter hands back the guarded issue-count surface for the
// proxied-server provider, through the provider's OWN capability accessor —
// the same two-step proxiedCommenter performs, and for the same reason: the
// accessor is where each layer is added.
func proxiedCounter() (issueops.Counter, error) {
	if uowProvider == nil {
		return nil, errors.New("proxied-server UOW provider not initialized")
	}
	src, ok := uowProvider.(uow.CounterSource)
	if !ok {
		return nil, fmt.Errorf("proxied-server provider %T does not offer the issue-count surface", uowProvider)
	}
	return src.Counter()
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Upgrade bd / the provider wiring so the proxied-server provider implements uow.CounterSource (the %T in the message names the missing concrete type)
  2. Bypass the proxy: point bd at the database directly so openCounter picks the non-proxied counter
  3. If you supply a custom provider, add the Counter() accessor required by uow.CounterSource
  4. Check for mixed-version installs (old binary with new server or vice versa) and align versions

Example fix

// before
type myProvider struct{} // lacks Counter()
// after
func (p *myProvider) Counter() (issueops.Counter, error) { return p.src.Counter() } // implement uow.CounterSource
Defensive patterns

Strategy: type-guard

Validate before calling

// Before relying on the proxied counter, assert the capability
if _, ok := uowProvider.(uow.CounterSource); !ok {
    // fall back to direct-DB counting or fail fast with a clear message
}

Type guard

func hasCounter(p any) bool {
    _, ok := p.(uow.CounterSource)
    return ok
}

Try / catch

counter, err := openCounter(ctx)
if err != nil {
    if strings.Contains(err.Error(), "does not offer the issue-count surface") {
        // upgrade provider / bypass proxy
    }
    return err
}

Prevention

When it happens

Trigger: A command routes counting through the proxied-server provider while uowProvider holds a concrete type that does not implement uow.CounterSource — e.g. a provider build that only registers the comment surface (proxiedCommenter) or a partially initialized proxy stack; also reachable via openCounter whenever the current route selects the proxied server.

Common situations: Running against a proxied server whose client bundle predates the issue-count capability; embedding or stubbing a custom provider in tests/tools without implementing Counter(); version skew between the bd binary and the proxy provider wiring.

Related errors


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