{"record":{"id":"4d4c5b15b790e1f1","repo":"hashicorp/nomad","slug":"decompression-file-count-limit-must-be-0-but-fo","errorCode":null,"errorMessage":"decompression_file_count_limit must be >= 0 but found %d","messagePattern":"decompression_file_count_limit must be >= 0 but found (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/config/artifact.go","lineNumber":224,"sourceCode":"\t\treturn fmt.Errorf(\"hg_timeout not a valid duration: %w\", err)\n\t} else if v < 0 {\n\t\treturn fmt.Errorf(\"hg_timeout must be > 0\")\n\t}\n\n\tif a.S3Timeout == nil {\n\t\treturn fmt.Errorf(\"s3_timeout must be set\")\n\t}\n\tif v, err := time.ParseDuration(*a.S3Timeout); err != nil {\n\t\treturn fmt.Errorf(\"s3_timeout not a valid duration: %w\", err)\n\t} else if v < 0 {\n\t\treturn fmt.Errorf(\"s3_timeout must be > 0\")\n\t}\n\n\tif a.DecompressionFileCountLimit == nil {\n\t\treturn fmt.Errorf(\"decompression_file_count_limit must not be nil\")\n\t}\n\tif v := *a.DecompressionFileCountLimit; v < 0 {\n\t\treturn fmt.Errorf(\"decompression_file_count_limit must be >= 0 but found %d\", v)\n\t}\n\n\tif a.DecompressionSizeLimit == nil {\n\t\treturn fmt.Errorf(\"decompression_size_limit must not be nil\")\n\t}\n\tif v, err := humanize.ParseBytes(*a.DecompressionSizeLimit); err != nil {\n\t\treturn fmt.Errorf(\"decompression_size_limit is not a valid size: %w\", err)\n\t} else if v > math.MaxInt64 {\n\t\treturn fmt.Errorf(\"decompression_size_limit must be < %d but found %d\", int64(math.MaxInt64), v)\n\t}\n\n\tif a.DisableArtifactInspection == nil {\n\t\treturn fmt.Errorf(\"disable_artifact_inspection must be set\")\n\t}\n\n\tif a.DisableFilesystemIsolation == nil {\n\t\treturn fmt.Errorf(\"disable_filesystem_isolation must be set\")\n\t}","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/config/artifact.go#L206-L242","documentation":"Validate() enforces that decompression_file_count_limit is non-negative; a negative value fails with 'must be >= 0 but found %d'. A negative archive-file cap is meaningless and typically signals a config mistake rather than intent to disable the check.","triggerScenarios":"Calling ArtifactConfig.Validate() when *a.DecompressionFileCountLimit < 0, e.g. -1 or -5000.","commonSituations":"Using -1 to mean 'unlimited' (not supported here); int truncation/overflow when the value is computed in Go or a template; typos like `=-0` or sign dropped in interpolation.","solutions":["Change decompression_file_count_limit to a non-negative integer, e.g. 0 (0 archives disallowed effectively) or a real cap like 10000.","If 'unlimited' is desired, set the maximum int value that fits the platform rather than a negative number.","Add a pre-validate check that clamps or rejects negative values at config-load time with a clearer message."],"exampleFix":"// before\nartifact {\n  decompression_file_count_limit = -1\n}\n// after\nartifact {\n  decompression_file_count_limit = 10000\n}","handlingStrategy":"validation","validationCode":"if cfg.DecompressionFileCountLimit != nil && *cfg.DecompressionFileCountLimit < 0 {\n    return fmt.Errorf(\"decompression_file_count_limit must be >= 0, got %d\", *cfg.DecompressionFileCountLimit)\n}","typeGuard":"func nonNegativeLimit(p *int) bool { return p != nil && *p >= 0 }","tryCatchPattern":null,"preventionTips":["Do not use -1 as an 'unlimited' sentinel in Nomad artifact limits.","Check for int overflow when the value is computed at runtime.","Add range assertions in config-loading unit tests."],"tags":["nomad","config-validation","integer-range","decompression"],"backgroundTag":"config-value-out-of-range","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"}