{"record":{"id":"5ce24ca80cde7894","repo":"nektos/act","slug":"parse-q-w","errorCode":null,"errorMessage":"parse %q: %w","messagePattern":"parse %q: %w","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"pkg/artifactcache/handler.go","lineNumber":569,"sourceCode":"\t\th.logger.Errorf(\"%v %v: %v\", r.Method, r.RequestURI, err)\n\t\tdata, _ = json.Marshal(map[string]any{\n\t\t\t\"error\": err.Error(),\n\t\t})\n\t} else {\n\t\tdata, _ = json.Marshal(v[0])\n\t}\n\tw.WriteHeader(code)\n\t_, _ = w.Write(data)\n}\n\nfunc parseContentRange(s string) (int64, int64, error) {\n\t// support the format like \"bytes 11-22/*\" only\n\ts, _, _ = strings.Cut(strings.TrimPrefix(s, \"bytes \"), \"/\")\n\ts1, s2, _ := strings.Cut(s, \"-\")\n\n\tstart, err := strconv.ParseInt(s1, 10, 64)\n\tif err != nil {\n\t\treturn 0, 0, fmt.Errorf(\"parse %q: %w\", s, err)\n\t}\n\tstop, err := strconv.ParseInt(s2, 10, 64)\n\tif err != nil {\n\t\treturn 0, 0, fmt.Errorf(\"parse %q: %w\", s, err)\n\t}\n\treturn start, stop, nil\n}\n","sourceCodeStart":551,"sourceCodeEnd":577,"githubUrl":"https://github.com/nektos/act/blob/4f411281417e88660bea1c1a1749aa71ae0bd60f/pkg/artifactcache/handler.go#L551-L577","documentation":"parseContentRange parses the Content-Range header of chunked cache uploads but only supports the 'bytes START-STOP/*' form. After stripping the 'bytes ' prefix and cutting at '/', it strconv.ParseInt's the segment before the '-'. This error means the start-offset portion was not a valid integer — e.g. 'bytes a-5/*', 'bytes -5/*' (empty start), or a completely different header shape.","triggerScenarios":"A PATCH request to the local cache server (handler.go:277) whose Content-Range header has a non-numeric or missing start value. Usually produced by a caching action version that formats Content-Range differently than 'bytes N-M/*'.","commonSituations":"Using actions/cache versions whose upload client sends 'bytes */N' or bare offsets; a custom action or curl-based test PATCH with a hand-written header; proxies/retries mangling the header.","solutions":["Pin/upgrade to actions/cache@v3 (or v4) which act's cache server is built against","If calling the API manually, send Content-Range exactly as 'bytes <start>-<stop>/*'","Log the raw header value at the handler to confirm what the client actually sent","Check for HTTP middleware/proxies that rewrite or strip Content-Range"],"exampleFix":"// curl upload with correct header\ncurl -X PATCH \"http://localhost:8080/_apis/artifactcache/cache/<id>\" \\\n  -H \"Content-Range: bytes 0-1023/*\" \\\n  --data-binary @chunk.bin","handlingStrategy":"validation","validationCode":"// validate Content-Range before using it\nfunc validContentRange(s string) bool {\n    body := strings.TrimPrefix(s, \"bytes \")\n    body, _, _ = strings.Cut(body, \"/\")\n    s1, s2, ok := strings.Cut(body, \"-\")\n    if !ok { return false }\n    _, e1 := strconv.ParseInt(s1, 10, 64)\n    _, e2 := strconv.ParseInt(s2, 10, 64)\n    return e1 == nil && e2 == nil\n}","typeGuard":null,"tryCatchPattern":"start, stop, err := parseContentRange(hdr)\nif err != nil {\n    http.Error(w, \"400 bad Content-Range: \"+err.Error(), http.StatusBadRequest)\n    return\n}","preventionTips":["Always send 'bytes START-STOP/*' with both offsets numeric","Pin actions/cache versions compatible with act (v3+)","Log raw Content-Range headers when debugging upload clients"],"tags":["artifact-cache","http","content-range","parsing","act"],"backgroundTag":null,"analyzedSha":"4f411281417e88660bea1c1a1749aa71ae0bd60f","analyzedAt":"2026-08-15T09:19:46.307Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}