googleapis/mcp-toolbox · error

unable to parse Timeout string as time.Duration: %s

Error message

unable to parse Timeout string as time.Duration: %s

What it means

The Looker source stores its client timeout as a string; Initialize parses it with time.ParseDuration. If the string is not a valid Go duration (e.g. "30" without a unit), initialization fails with this error. The parse error text is appended for diagnosis.

Source

Thrown at internal/sources/looker/looker.go:104

func (r Config) SourceConfigType() string {
	return SourceType
}

// Initialize initializes a Looker Source instance.
func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) {
	logger, err := util.LoggerFromContext(ctx)
	if err != nil {
		return nil, fmt.Errorf("unable to get logger from ctx: %s", err)
	}

	userAgent, err := util.UserAgentFromContext(ctx)
	if err != nil {
		return nil, err
	}

	duration, err := time.ParseDuration(r.Timeout)
	if err != nil {
		return nil, fmt.Errorf("unable to parse Timeout string as time.Duration: %s", err)
	}

	if !r.SslVerification {
		logger.WarnContext(ctx, "Insecure HTTP is enabled for Looker source %s. TLS certificate verification is skipped.\n", r.Name)
	}
	cfg := rtl.ApiSettings{
		AgentTag:     userAgent,
		BaseUrl:      r.BaseURL,
		ApiVersion:   "4.0",
		VerifySsl:    r.SslVerification,
		Timeout:      int32(duration.Seconds()),
		ClientId:     r.ClientId,
		ClientSecret: r.ClientSecret,
	}

	var tokenSource oauth2.TokenSource
	tokenSource, _ = initGoogleCloudConnection(ctx)

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Set timeout to a valid Go duration string with a unit, e.g. "30s" or "2m".
  2. If the field was intended to be empty/default, remove it so the default is used.
  3. Validate the YAML (go duration syntax: number + unit suffix like ns/us/ms/s/m/h).

Example fix

# before
sources:
  looker:
    kind: looker
    timeout: "30"
# after
sources:
  looker:
    kind: looker
    timeout: "30s"
Defensive patterns

Strategy: validation

Validate before calling

// Go: validate the timeout config value before building the source config
d, err := time.ParseDuration(cfg.Timeout)
if err != nil {
    return fmt.Errorf("looker timeout %q is not a valid Go duration (e.g. 30s, 2m): %w", cfg.Timeout, err)
}

Try / catch

src, err := cfg.Initialize(ctx, tracer)
if err != nil {
    if strings.Contains(err.Error(), "unable to parse Timeout string") {
        fmt.Printf("timeout %q must be a Go duration string like 30s — fix YAML\n", cfg.Timeout)
    }
    return err
}

Prevention

When it happens

Trigger: Config with timeout: "30" (missing unit), "thirty", or an empty-but-nonzero string; anything time.ParseDuration rejects. Valid examples: "30s", "1m30s".

Common situations: Copy-pasting a timeout in seconds/milliseconds as a bare integer from other tooling; editing YAML and dropping the 's' suffix; assuming the field takes milliseconds.

Understand the failure class

Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.

Related errors


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