googleapis/mcp-toolbox · error

failed to get logger from context: %w

Error message

failed to get logger from context: %w

What it means

validateOpaqueToken begins by extracting the structured logger from the context via util.LoggerFromContext; if no logger is present in ctx, the introspection flow cannot proceed and this wrapped error is returned. It indicates a programming/setup issue rather than a token problem — the caller passed a bare context.Context.

Source

Thrown at internal/auth/generic/generic.go:346

	aud, err := claims.GetAudience()
	if err != nil {
		return nil, &MCPAuthError{Code: http.StatusUnauthorized, Message: "could not parse audience from token", ScopesRequired: a.ScopesRequired}
	}

	scopeClaim, _ := claims["scope"].(string)

	err = a.validateClaims(ctx, iss, aud, scopeClaim)
	if err != nil {
		return nil, err
	}
	return claims, nil
}

// validateOpaqueToken validates an opaque token by calling the introspection endpoint
func (a AuthService) validateOpaqueToken(ctx context.Context, tokenStr string) (map[string]any, error) {
	logger, err := util.LoggerFromContext(ctx)
	if err != nil {
		return nil, fmt.Errorf("failed to get logger from context: %w", err)
	}

	introspectionURL := a.introspectionURL
	if introspectionURL == "" {
		introspectionURL, err = url.JoinPath(a.AuthorizationServer, "introspect")
		if err != nil {
			return nil, fmt.Errorf("failed to construct introspection URL: %w", err)
		}
	}

	paramName := a.IntrospectionParamName
	if paramName == "" {
		paramName = "token"
	}

	var req *http.Request
	if a.IntrospectionMethod == "GET" {
		u, err := url.Parse(introspectionURL)

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Ensure the server's logging middleware runs before auth so the logger is stored in the request context.
  2. In custom code, attach the logger: ctx := util.WithLogger(ctx, logger) before calling ValidateMCPAuth.
  3. If in tests, use the project's context helpers to inject a test logger instead of context.Background().

Example fix

// before
svc.ValidateMCPAuth(ctx, header) // ctx = context.Background()
// after
ctx = util.WithLogger(ctx, slog.Default())
svc.ValidateMCPAuth(ctx, header)
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := util.LoggerFromContext(ctx); err != nil {
    ctx = util.WithLogger(ctx, slog.Default())
}
return svc.ValidateMCPAuth(ctx, header)

Type guard

func ctxHasLogger(ctx context.Context) bool {
    _, err := util.LoggerFromContext(ctx)
    return err == nil
}

Try / catch

claims, err := svc.ValidateMCPAuth(ctx, header)
if err != nil {
    if strings.Contains(err.Error(), "failed to get logger from context") {
        // programmer error: attach logger to ctx before calling auth
        ctx = util.WithLogger(ctx, slog.Default())
        claims, err = svc.ValidateMCPAuth(ctx, header)
    }
    return claims, err
}

Prevention

When it happens

Trigger: ValidateMCPAuth (or another caller) invokes validateOpaqueToken with a ctx that never had a logger attached, so util.LoggerFromContext returns an error which is wrapped here.

Common situations: Custom embedding of the toolbox server that constructs requests without the project's logger middleware, unit tests passing context.Background(), or a request path that bypasses the logging middleware that injects the logger.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/33e1eb658a21044c. Report an issue: GitHub.