Reading Wire Errors
Wire errors are compile-time graph errors.
When forj build fails during Wire generation, the App graph could not be constructed from the provider sets. The fix is usually to add, remove, or move a provider. Do not edit wire/wire_gen.go.
Read The Chain
Start with the type Wire could not provide, then follow who needed it.
Simplified output:
wire: no provider found for *myapp/internal/users.Service
needed by *myapp/internal/users.Controller in provider "NewController"
needed by httpAppControllerSetThis says:
users.Controllerneeds*users.Service.- Wire cannot find a provider that returns
*users.Service. - The failing graph is the HTTP controller graph.
The fix is not to edit wire/wire_gen.go. Add the missing service provider to the set that provides application services.
Missing Provider
Likely cause: a constructor needs a value that no provider returns.
func NewController(service *users.Service) *Controller {
return &Controller{service: service}
}Fix:
var appSet = wire.NewSet(
// existing framework and app providers...
users.NewService,
)Keep the controller in the HTTP controller set:
var httpAppControllerSet = wire.NewSet(
// existing controllers...
users.NewController,
)Use Wiring Recipes when you are unsure which set owns a constructor.
Wrong Set
Likely cause: the provider exists, but it was added to a set that is not used by the failing graph.
Check the file names:
| Value | Usually belongs in |
|---|---|
| Application service | wire/inject_app_services.go |
| HTTP controller | wire/inject_http_controllers.go |
| App command | internal/cmd/wire.go |
| Job handler | wire/inject_jobs_app.go when jobs are enabled |
If the error is about a controller, adding the service constructor to the controller set is usually the wrong fix. Controllers belong in the controller set; services belong in the app services set.
Duplicate Provider
Likely cause: two providers in the same graph return the same type.
Simplified output:
wire: multiple providers for *httpx.Client
current:
provider "ProvideBillingHTTPClient"
previous:
provider "ProvideSearchHTTPClient"Prefer domain-specific adapter types:
type BillingGateway struct {
http *httpx.Client
}
type SearchIndexer struct {
http *httpx.Client
}Then provide *billing.BillingGateway and *search.SearchIndexer, not two raw *httpx.Client values.
If the duplicate is accidental, remove one provider from the set.
Interface Mismatch
Likely cause: a constructor asks for an interface, but the provider returns a concrete type.
func NewService(gateway Gateway) *Service {
return &Service{gateway: gateway}
}If the provider owns the implementation choice, return the interface:
func ProvideGateway(cfg GatewayConfig) (Gateway, error) {
if !cfg.Enabled {
return NewDisabledGateway(), nil
}
return NewHTTPGateway(cfg), nil
}Use concrete types when there is only one implementation and no useful abstraction boundary.
Type Mismatch
Wire matches exact Go types.
These are different types:
*billing.Gateway
billing.Gateway
*search.GatewayWhen a constructor asks for billing.Gateway, a provider returning *billing.HTTPGateway will not satisfy it unless the provider returns billing.Gateway or the graph explicitly binds that concrete type to the interface.
Stale Generated Output
Likely cause: provider sets, generated components, or constructor signatures changed, but the graph was not regenerated.
Run:
forj buildDo not manually edit:
wire/wire_gen.goChange providers, constructors, or generated component inputs, then regenerate.
Fast Checklist
When Wire fails:
- Find the missing or duplicated type.
- Find the constructor that asked for it.
- Confirm exactly one provider returns that type.
- Confirm the provider is in the set used by the failing graph.
- Confirm constructor parameter types match provider return types exactly.
- Confirm interfaces are intentional.
- Run
forj buildafter changing the provider set.
Next Steps
- Wiring Recipes maps values to generated provider sets.
- Provider Patterns shows provider shapes for adapters and optional features.
