googleapis/mcp-toolbox · error
error getting logger from context in ExtractLookerFieldPrope
Error message
error getting logger from context in ExtractLookerFieldProperties: %v
What it means
ExtractLookerFieldProperties fetches the logger from the context via util.LoggerFromContext. If the context carries no logger, it cannot log field extraction progress, so it aborts and returns this error instead of an empty field map.
Source
Thrown at internal/tools/looker/lookercommon/lookercommon.go:50
FiltersFields = "fields(filters(name,type,label,label_short,description,synonyms,tags,hidden,suggestable,suggestions,suggest_dimension,suggest_explore))"
MeasuresFields = "fields(measures(name,type,label,label_short,description,synonyms,tags,hidden,suggestable,suggestions,suggest_dimension,suggest_explore))"
ParametersFields = "fields(parameters(name,type,label,label_short,description,synonyms,tags,hidden,suggestable,suggestions,suggest_dimension,suggest_explore))"
)
// ExtractLookerFieldProperties extracts common properties from Looker field objects.
func ExtractLookerFieldProperties(ctx context.Context, fields *[]v4.LookmlModelExploreField, showHiddenFields bool) ([]any, error) {
data := make([]any, 0)
// Handle nil fields pointer
if fields == nil {
return data, nil
}
logger, err := util.LoggerFromContext(ctx)
if err != nil {
// This should ideally not happen if the context is properly set up.
// Log and return an empty map or handle as appropriate for your error strategy.
return data, fmt.Errorf("error getting logger from context in ExtractLookerFieldProperties: %v", err)
}
for _, v := range *fields {
logger.DebugContext(ctx, "Got response element of %v\n", v)
if v.Name != nil && strings.HasSuffix(*v.Name, "_raw") {
continue
}
if !showHiddenFields && v.Hidden != nil && *v.Hidden {
continue
}
vMap := make(map[string]any)
if v.Name != nil {
vMap["name"] = *v.Name
}
if v.Type != nil {
vMap["type"] = *v.Type
}
if v.Label != nil {View on GitHub (pinned to 8cc6e09de2)
Solutions
- Use the request context propagated by the toolbox server, which embeds the logger.
- In tests or standalone code, attach a logger first: ctx := util.ContextWithLogger(ctx, logger).
- If spawning goroutines, pass the parent (logger-carrying) context or re-attach the logger.
Example fix
// before fields, err := lookercommon.ExtractLookerFieldProperties(context.Background(), resp) // after logger := slog.Default() ctx := util.ContextWithLogger(context.Background(), logger) fields, err := lookercommon.ExtractLookerFieldProperties(ctx, resp)
Defensive patterns
Strategy: validation
Validate before calling
// Ensure a logger is present before calling
if _, err := util.LoggerFromContext(ctx); err != nil {
ctx = util.ContextWithLogger(ctx, slog.Default())
} Try / catch
fields, err := lookercommon.ExtractLookerFieldProperties(ctx, resp)
if err != nil && strings.Contains(err.Error(), "error getting logger") {
ctx = util.ContextWithLogger(ctx, slog.Default())
fields, err = lookercommon.ExtractLookerFieldProperties(ctx, resp)
} Prevention
- Always derive invoke contexts from the server request context.
- In tests, use a test helper that attaches a slog logger to every context.
- Never spawn goroutines with a brand-new context.Background(); pass the parent ctx.
When it happens
Trigger: Calling ExtractLookerFieldProperties with a ctx that never had a logger attached (e.g., a raw context.Background() in tests or a code path bypassing the server's context middleware).
Common situations: Unit tests calling the helper directly with a bare context; custom invoke wrappers dropping the logger middleware; background goroutines spawned with a new context.
Related errors
- unable to get logger from ctx: %s
- unable to get logger from ctx: %s
- 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/238b70c83078c76a.
Report an issue: GitHub.