jaegertracing/jaeger · error
dial: %w
Error message
dial: %w
What it means
The ACP health check dials the agent's WebSocket endpoint (via DialWsAdapter) to verify the agent is reachable; if the dial fails the check returns "dial: <cause>". It exists so the jaegerquery AI extension can report agent connectivity as unhealthy instead of hanging or erroring obscurely later.
Source
Thrown at cmd/jaeger/internal/extension/jaegerquery/internal/jaegerai/aihealth/acp_check.go:44
// level errors are still returned to the caller from acp.SendRequest, so
// nothing diagnostic is lost.
var silentACPLogger = slog.New(slog.NewTextHandler(io.Discard, nil))
// NewACPCheck returns a check function that opens a fresh WebSocket
// connection to agentURL, performs one ACP `initialize` round-trip, and
// closes. Any transport-level or protocol-level error counts as unhealthy.
// Suitable for use as aihealth.Config.Check.
func NewACPCheck(agentURL string, agentHeaders configopaque.MapList, logger *zap.Logger) func(ctx context.Context) error {
// The check only sends `initialize` and immediately closes — the sidecar
// should never send a client-bound call in that window, but if it does we
// refuse it rather than crash.
noopMethodHandler := func(_ context.Context, method string, _ json.RawMessage) (any, *acp.RequestError) {
return nil, acp.NewMethodNotFound(method)
}
return func(ctx context.Context) error {
adapter, err := jaegerai.DialWsAdapter(ctx, agentURL, agentHeaders, logger)
if err != nil {
return fmt.Errorf("dial: %w", err)
}
defer adapter.Close()
conn := acp.NewConnection(noopMethodHandler, adapter, adapter)
conn.SetLogger(silentACPLogger)
req := acp.InitializeRequest{
ProtocolVersion: acp.ProtocolVersionNumber,
ClientCapabilities: acp.ClientCapabilities{
Fs: acp.FileSystemCapabilities{ReadTextFile: false, WriteTextFile: false},
Terminal: false,
},
ClientInfo: &acp.Implementation{
Name: "jaeger-ai-check",
Version: version.Get().GitVersion,
},
}
if _, err := acp.SendRequest[acp.InitializeResponse](conn, ctx, acp.AgentMethodInitialize, req); err != nil {View on GitHub (pinned to 806f444784)
Solutions
- Verify the agent URL (scheme ws:// or wss://, host, port, path) in the AI extension config.
- Confirm the agent process is running and listening on that address (curl the endpoint / check its logs).
- If the dial fails with an HTTP error status, check the Jaeger log for 'WebSocket dial failed' with status/body to see auth or routing rejection details.
- Add required agent_headers (e.g. Authorization) if the agent requires auth.
Defensive patterns
Strategy: retry
Validate before calling
u, err := url.Parse(agentURL)
if err != nil || (u.Scheme != "ws" && u.Scheme != "wss") {
return fmt.Errorf("invalid agent URL: %q", agentURL)
} Try / catch
err := check(ctx)
if err != nil && strings.HasPrefix(err.Error(), "dial: ") {
// do not tight-loop; back off and re-check agent availability
time.Sleep(backoff)
err = check(ctx)
} Prevention
- Start the agent before jaeger-query or rely on the extension's readiness reporting instead of assuming startup order.
- Validate ws:// or wss:// scheme, host, port and path in configuration.
- Ensure network policies/proxies allow WebSocket upgrades to the agent.
When it happens
Trigger: Health check runs and DialWsAdapter cannot establish the WebSocket: agent URL wrong, agent process down, TLS rejection, or the HTTP upgrade handshake returns a non-101 status.
Common situations: Agent not yet started when Jaeger boots; wrong port/path in the agent URL; missing agent_headers causing an auth-rejecting 401/403 on the upgrade request; network policy blocking the connection.
Related errors
- websocket dial %s: %w
- cannot start the admin server: %w
- abnormal value of http status code: %v
- initialize: %w
- invalid HTTP server host:port: %w
AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01).
Data as JSON: /api/errors/0bddb188027c5b7c.
Report an issue: GitHub.