{"record":{"id":"5cb8da35f7431aeb","repo":"googleapis/mcp-toolbox","slug":"unable-to-get-logger-from-ctx-s-5cb8da","errorCode":null,"errorMessage":"unable to get logger from ctx: %s","messagePattern":"unable to get logger from ctx: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/tools/looker/lookercommon/lookercommon.go","lineNumber":295,"sourceCode":"// wildcards and rejects them for unquoted parameters, so an unescaped value\n// like `first_touch` is parsed as `first<single-char-wildcard>touch` and 400s\n// with \"The filter \\\"first_touch\\\" is not allowed.\" This is a no-op when no\n// filters target unquoted parameters. Metadata-lookup failures are returned to\n// the caller, which should log and proceed: callers without explore-read\n// permission still need their non-parameter queries to succeed.\nfunc EscapeUnquotedParameterFilters(ctx context.Context, sdk *v4.LookerSDK, wq *v4.WriteQuery, opts *rtl.ApiSettings) error {\n\tunquoted, err := resolveUnquotedParameterNames(ctx, sdk, wq, opts)\n\tif err != nil {\n\t\treturn err\n\t}\n\tEscapeFiltersForUnquotedParameters(wq, unquoted)\n\treturn nil\n}\n\nfunc ProcessQueryArgs(ctx context.Context, params parameters.ParamValues) (*v4.WriteQuery, error) {\n\tlogger, err := util.LoggerFromContext(ctx)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"unable to get logger from ctx: %s\", err)\n\t}\n\n\tlogger.DebugContext(ctx, \"params = \", params)\n\tparamsMap := params.AsMap()\n\n\tf, err := parameters.ConvertAnySliceToTyped(paramsMap[\"fields\"].([]any), \"string\")\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"can't convert fields to array of strings: %s\", err)\n\t}\n\tfields := f.([]string)\n\tfilters := paramsMap[\"filters\"].(map[string]any)\n\t// Strip a single layer of wrapping quotes from keys and string values.\n\t// Values matter for LookML `type: unquoted` parameters, where Looker\n\t// substitutes the value bare into SQL via {% parameter %}. Build a new map\n\t// rather than mutating during iteration, and avoid comparing `any` values\n\t// directly (non-comparable dynamic types like slices would panic).\n\tprocessedFilters := make(map[string]any, len(filters))\n\tfor k, v := range filters {","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/tools/looker/lookercommon/lookercommon.go#L277-L313","documentation":"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.","triggerScenarios":"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).","commonSituations":"Unit tests constructing ParamValues and calling ProcessQueryArgs directly; custom dispatch paths dropping the logger; refactors that create a fresh context mid-request.","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."],"exampleFix":"// before\nq, err := lookercommon.ProcessQueryArgs(context.Background(), params)\n// after\nctx := util.ContextWithLogger(context.Background(), slog.Default())\nq, err := lookercommon.ProcessQueryArgs(ctx, params)\n","handlingStrategy":"validation","validationCode":"if _, err := util.LoggerFromContext(ctx); err != nil {\n    ctx = util.ContextWithLogger(ctx, slog.Default())\n}\nq, err := lookercommon.ProcessQueryArgs(ctx, params)","typeGuard":null,"tryCatchPattern":"q, err := lookercommon.ProcessQueryArgs(ctx, params)\nif err != nil && strings.Contains(err.Error(), \"unable to get logger\") {\n    // re-attach logger and retry once\n    ctx = util.ContextWithLogger(ctx, slog.Default())\n    q, err = lookercommon.ProcessQueryArgs(ctx, params)\n}","preventionTips":["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."],"tags":["logging","context","looker"],"backgroundTag":"missing-logger-in-context","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}