googleapis/mcp-toolbox · error
unable to get logger from ctx: %s
Error message
unable to get logger from ctx: %s
What it means
Runtime guard in ProcessQueryArgs: the request context does not carry a logger (LoggerFromContext failed), so query processing cannot proceed with structured logging. Usually indicates the call bypassed the normal server middleware chain.
Source
Thrown at internal/tools/looker/lookercommon/lookercommon.go:295
// wildcards and rejects them for unquoted parameters, so an unescaped value
// like `first_touch` is parsed as `first<single-char-wildcard>touch` and 400s
// with "The filter \"first_touch\" is not allowed." This is a no-op when no
// filters target unquoted parameters. Metadata-lookup failures are returned to
// the caller, which should log and proceed: callers without explore-read
// permission still need their non-parameter queries to succeed.
func EscapeUnquotedParameterFilters(ctx context.Context, sdk *v4.LookerSDK, wq *v4.WriteQuery, opts *rtl.ApiSettings) error {
unquoted, err := resolveUnquotedParameterNames(ctx, sdk, wq, opts)
if err != nil {
return err
}
EscapeFiltersForUnquotedParameters(wq, unquoted)
return nil
}
func ProcessQueryArgs(ctx context.Context, params parameters.ParamValues) (*v4.WriteQuery, error) {
logger, err := util.LoggerFromContext(ctx)
if err != nil {
return nil, fmt.Errorf("unable to get logger from ctx: %s", err)
}
logger.DebugContext(ctx, "params = ", params)
paramsMap := params.AsMap()
f, err := parameters.ConvertAnySliceToTyped(paramsMap["fields"].([]any), "string")
if err != nil {
return nil, fmt.Errorf("can't convert fields to array of strings: %s", err)
}
fields := f.([]string)
filters := paramsMap["filters"].(map[string]any)
// Strip a single layer of wrapping quotes from keys and string values.
// Values matter for LookML `type: unquoted` parameters, where Looker
// substitutes the value bare into SQL via {% parameter %}. Build a new map
// rather than mutating during iteration, and avoid comparing `any` values
// directly (non-comparable dynamic types like slices would panic).
processedFilters := make(map[string]any, len(filters))
for k, v := range filters {View on GitHub (pinned to 8cc6e09de2)
Solutions
- Pass the server-provided request context through to the tool invocation.
- Attach a logger explicitly: ctx := util.ContextWithLogger(ctx, logger).
- In tests, build a context with a logger before calling ProcessQueryArgs.
Example fix
// before q, err := lookercommon.ProcessQueryArgs(context.Background(), params) // after ctx := util.ContextWithLogger(context.Background(), slog.Default()) q, err := lookercommon.ProcessQueryArgs(ctx, params)
Defensive patterns
Strategy: validation
Validate before calling
if _, err := util.LoggerFromContext(ctx); err != nil {
ctx = util.ContextWithLogger(ctx, slog.Default())
}
q, err := lookercommon.ProcessQueryArgs(ctx, params) Try / catch
q, err := lookercommon.ProcessQueryArgs(ctx, params)
if err != nil && strings.Contains(err.Error(), "unable to get logger") {
// re-attach logger and retry once
ctx = util.ContextWithLogger(ctx, slog.Default())
q, err = lookercommon.ProcessQueryArgs(ctx, params)
} Prevention
- Thread the server request context through all invoke paths.
- Add a middleware/unit-test helper guaranteeing a logger-bearing context.
- Audit code paths that create fresh contexts mid-request.
When it happens
Trigger: Calling ProcessQueryArgs with a context that was never decorated with a logger by the server middleware (bare context.Background(), new goroutine contexts, direct test calls).
Common situations: Unit tests constructing ParamValues and calling ProcessQueryArgs directly; custom dispatch paths dropping the logger; refactors that create a fresh context mid-request.
Related errors
- unable to get logger from ctx: %s
- error getting logger from context in ExtractLookerFieldPrope
- unable to get logger from ctx: %s
- unable to get logger from ctx: %s
- failed to get logger from context: %w
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/5cb8da35f7431aeb.
Report an issue: GitHub.