nektos/act · error
parse %q: %w
Error message
parse %q: %w
What it means
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.
Source
Thrown at pkg/artifactcache/handler.go:569
h.logger.Errorf("%v %v: %v", r.Method, r.RequestURI, err)
data, _ = json.Marshal(map[string]any{
"error": err.Error(),
})
} else {
data, _ = json.Marshal(v[0])
}
w.WriteHeader(code)
_, _ = w.Write(data)
}
func parseContentRange(s string) (int64, int64, error) {
// support the format like "bytes 11-22/*" only
s, _, _ = strings.Cut(strings.TrimPrefix(s, "bytes "), "/")
s1, s2, _ := strings.Cut(s, "-")
start, err := strconv.ParseInt(s1, 10, 64)
if err != nil {
return 0, 0, fmt.Errorf("parse %q: %w", s, err)
}
stop, err := strconv.ParseInt(s2, 10, 64)
if err != nil {
return 0, 0, fmt.Errorf("parse %q: %w", s, err)
}
return start, stop, nil
}
View on GitHub (pinned to 4f41128141)
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
Example fix
// curl upload with correct header curl -X PATCH "http://localhost:8080/_apis/artifactcache/cache/<id>" \ -H "Content-Range: bytes 0-1023/*" \ --data-binary @chunk.bin
Defensive patterns
Strategy: validation
Validate before calling
// validate Content-Range before using it
func validContentRange(s string) bool {
body := strings.TrimPrefix(s, "bytes ")
body, _, _ = strings.Cut(body, "/")
s1, s2, ok := strings.Cut(body, "-")
if !ok { return false }
_, e1 := strconv.ParseInt(s1, 10, 64)
_, e2 := strconv.ParseInt(s2, 10, 64)
return e1 == nil && e2 == nil
} Try / catch
start, stop, err := parseContentRange(hdr)
if err != nil {
http.Error(w, "400 bad Content-Range: "+err.Error(), http.StatusBadRequest)
return
} Prevention
- 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
When it happens
Trigger: 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/*'.
Common situations: 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.
Related errors
- find cache: %w
- insert cache: %w
- write back id to db: %w
- broken file: %v != %v
- invalid publish opts format (should be name=value but got '%
AI-assisted analysis of nektos/act@4f41128141 (2026-08-15).
Data as JSON: /api/errors/5ce24ca80cde7894.
Report an issue: GitHub.