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
- Set timeout to a valid Go duration string with a unit, e.g. "30s" or "2m".
- If the field was intended to be empty/default, remove it so the default is used.
- 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
- Always include a unit suffix in timeout values: 30s, 5m — never a bare integer.
- Lint toolbox YAML for Go duration fields in CI.
- Remember the field is a string; millisecond integers from other tools must be converted.
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.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- invalid retryBaseDelay: %w
- description is required for tool %q
- description is required for tool %q
- description is required for tool %q
- description is required for tool %q
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/6290c032a592bc08.
Report an issue: GitHub.