googleapis/mcp-toolbox · warning

unable to get logger from ctx: %s

Error message

unable to get logger from ctx: %s

What it means

checkDBConnections retrieves a structured logger from the request context via util.LoggerFromContext; if the context carries no logger it returns this error. The pulse checks rely on contextual logging, so a bare context.Background() without the server's logger injection will fail. It indicates the tool was invoked outside the server's normal request pipeline.

Source

Thrown at internal/tools/looker/lookerhealthpulse/lookerhealthpulse.go:210

		return t.checkDashboardPerformance(ctx, source)
	case "check_dashboard_errors":
		return t.checkDashboardErrors(ctx, source)
	case "check_explore_performance":
		return t.checkExplorePerformance(ctx, source)
	case "check_schedule_failures":
		return t.checkScheduleFailures(ctx, source)
	case "check_legacy_features":
		return t.checkLegacyFeatures(ctx, source)
	default:
		return nil, fmt.Errorf("unknown action: %s", params.Action)
	}
}

// Check DB connections and run tests
func (t *pulseTool) checkDBConnections(ctx context.Context, source compatibleSource) (interface{}, error) {
	logger, err := util.LoggerFromContext(ctx)
	if err != nil {
		return nil, fmt.Errorf("unable to get logger from ctx: %s", err)
	}
	logger.InfoContext(ctx, "Test 1/6: Checking connections")

	reservedNames := map[string]struct{}{
		"looker__internal__analytics__replica": {},
		"looker__internal__analytics":          {},
		"looker":                               {},
		"looker__ilooker":                      {},
	}

	connections, err := t.SdkClient.AllConnections("", source.LookerApiSettings())
	if err != nil {
		return nil, fmt.Errorf("error fetching connections: %w", err)
	}

	var filteredConnections []v4.DBConnection
	for _, c := range connections {
		if _, reserved := reservedNames[*c.Name]; !reserved {

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Invoke the tool through the server's normal request path, which injects the logger into ctx.
  2. In tests or custom code, add a logger first: ctx = util.AddLoggerToContext(ctx, slog.Default()) (or the equivalent helper).
  3. Pass the request's context, not context.Background(), into Invoke.
  4. Check the util package for the exact logger context helper used by this version.

Example fix

// before
t.Invoke(ctx, src, params, token) // ctx = context.Background()
// after
logger := slog.Default()
ctx = util.AddLoggerToContext(context.Background(), logger)
t.Invoke(ctx, src, params, token)
Defensive patterns

Strategy: try-catch

Validate before calling

if util.LoggerFromContext(ctx) == nil /* or err != nil via helper */ {
    ctx = util.AddLoggerToContext(ctx, slog.Default())
}

Try / catch

result, toolErr := tool.Invoke(ctx, src, params, token)
if toolErr != nil && strings.Contains(toolErr.Error(), "unable to get logger") {
    ctx = util.AddLoggerToContext(ctx, slog.Default())
    result, toolErr = tool.Invoke(ctx, src, params, token)
}

Prevention

When it happens

Trigger: Calling checkDBConnections (via RunPulse/Invoke) with a context that was not populated by util.AddLoggerToContext / the server's middleware, e.g. in custom harnesses, tests, or scripts.

Common situations: Custom test harnesses passing context.Background(), background goroutines that drop the request context, or older server versions that did not inject a logger.

Related errors


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