{"record":{"id":"b0215417be28cee6","repo":"hashicorp/nomad","slug":"gcs-timeout-not-a-valid-duration-w","errorCode":null,"errorMessage":"gcs_timeout not a valid duration: %w","messagePattern":"gcs_timeout not a valid duration: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/config/artifact.go","lineNumber":188,"sourceCode":"\t\treturn fmt.Errorf(\"http_read_timeout not a valid duration: %w\", err)\n\t} else if v < 0 {\n\t\treturn fmt.Errorf(\"http_read_timeout must be > 0\")\n\t}\n\n\tif a.HTTPMaxSize == nil {\n\t\treturn fmt.Errorf(\"http_max_size must be set\")\n\t}\n\tif v, err := humanize.ParseBytes(*a.HTTPMaxSize); err != nil {\n\t\treturn fmt.Errorf(\"http_max_size not a valid size: %w\", err)\n\t} else if v > math.MaxInt64 {\n\t\treturn fmt.Errorf(\"http_max_size must be < %d but found %d\", int64(math.MaxInt64), v)\n\t}\n\n\tif a.GCSTimeout == nil {\n\t\treturn fmt.Errorf(\"gcs_timeout must be set\")\n\t}\n\tif v, err := time.ParseDuration(*a.GCSTimeout); err != nil {\n\t\treturn fmt.Errorf(\"gcs_timeout not a valid duration: %w\", err)\n\t} else if v < 0 {\n\t\treturn fmt.Errorf(\"gcs_timeout must be > 0\")\n\t}\n\n\tif a.GitTimeout == nil {\n\t\treturn fmt.Errorf(\"git_timeout must be set\")\n\t}\n\tif v, err := time.ParseDuration(*a.GitTimeout); err != nil {\n\t\treturn fmt.Errorf(\"git_timeout not a valid duration: %w\", err)\n\t} else if v < 0 {\n\t\treturn fmt.Errorf(\"git_timeout must be > 0\")\n\t}\n\n\tif a.HgTimeout == nil {\n\t\treturn fmt.Errorf(\"hg_timeout must be set\")\n\t}\n\tif v, err := time.ParseDuration(*a.HgTimeout); err != nil {\n\t\treturn fmt.Errorf(\"hg_timeout not a valid duration: %w\", err)","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/config/artifact.go#L170-L206","documentation":"Returned by ArtifactConfig.Validate when gcs_timeout is set but cannot be parsed by time.ParseDuration as a Go duration string. Valid formats include \"300ms\", \"5m\", \"1h30m\"; the wrapped error pinpoints the invalid syntax.","triggerScenarios":"Setting `gcs_timeout` to values like \"5\" (no unit), \"5 minutes\" (space and full word), \"5m30\" (trailing partial), \"\" (empty), or numeric-only input from environment/templating substitution.","commonSituations":"Confusing Go duration syntax with seconds-integer conventions used elsewhere; templating injecting an unquoted number; typos such as \"300sec\" or \"5min\"; copying values from non-Nomad tools with different duration formats.","solutions":["Use a valid Go duration string with a unit suffix, e.g. \"5m\", \"300s\", \"1h\".","Ensure templated/env-substituted values include the unit (e.g. append \"s\" for seconds).","Check the wrapped %w message to find the exact invalid portion of the string.","Validate the config with `nomad validate` before restarting the agent."],"exampleFix":"// before\nartifact {\n  gcs_timeout = \"300\"\n}\n// after\nartifact {\n  gcs_timeout = \"300s\"\n}","handlingStrategy":"validation","validationCode":"func validDuration(s *string) bool {\n    if s == nil { return false }\n    _, err := time.ParseDuration(*s)\n    return err == nil\n}","typeGuard":"func isDuration(s string) bool {\n    _, err := time.ParseDuration(s)\n    return err == nil\n}","tryCatchPattern":null,"preventionTips":["Always use Go duration syntax: number + unit (ms, s, m, h).","Append 's' when substituting raw seconds from env/templating.","Avoid locale-formatted numbers (no commas or spaces).","Lint config files with nomad validate before rollout."],"tags":["config","validation","duration","nomad"],"backgroundTag":"invalid-duration-format","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}