{"record":{"id":"f7b528fa4f204736","repo":"hashicorp/nomad","slug":"error-parsing-offset-v","errorCode":null,"errorMessage":"error parsing offset: %v","messagePattern":"error parsing offset: (.+?)","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"command/agent/fs_endpoint.go","lineNumber":151,"sourceCode":"\treturn reply.Info, nil\n}\n\nfunc (s *HTTPServer) FileReadAtRequest(resp http.ResponseWriter, req *http.Request) (any, error) {\n\tvar allocID, path string\n\tvar offset, limit int64\n\tvar err error\n\n\tq := req.URL.Query()\n\n\tif allocID = strings.TrimPrefix(req.URL.Path, \"/v1/client/fs/readat/\"); allocID == \"\" {\n\t\treturn nil, allocIDNotPresentErr\n\t}\n\tif path = q.Get(\"path\"); path == \"\" {\n\t\treturn nil, fileNameNotPresentErr\n\t}\n\n\tif offset, err = strconv.ParseInt(q.Get(\"offset\"), 10, 64); err != nil {\n\t\treturn nil, fmt.Errorf(\"error parsing offset: %v\", err)\n\t}\n\n\t// Parse the limit\n\tif limitStr := q.Get(\"limit\"); limitStr != \"\" {\n\t\tif limit, err = strconv.ParseInt(limitStr, 10, 64); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error parsing limit: %v\", err)\n\t\t}\n\t}\n\n\t// Create the request arguments\n\tfsReq := &cstructs.FsStreamRequest{\n\t\tAllocID:   allocID,\n\t\tPath:      path,\n\t\tOffset:    offset,\n\t\tOrigin:    \"start\",\n\t\tLimit:     limit,\n\t\tPlainText: true,\n\t}","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/command/agent/fs_endpoint.go#L133-L169","documentation":"The FileReadAtRequest HTTP handler (fs file read API) parses the required 'offset' query parameter as a base-10 int64. A missing or non-numeric offset makes strconv.ParseInt fail, and the error is wrapped and returned, rejecting the file read request.","triggerScenarios":"Calling GET /v1/client/fs/readat with offset absent or set to a non-integer (offset=abc, offset=, offset=1.5) — note the empty-string check earlier only guards 'path', so offset=\"\" also fails here.","commonSituations":"Hand-rolled scripts hitting the filesystem API omitting offset; passing byte counts with units like '10KB'; floating-point offsets from JSON-derived code; forgetting URL encoding.","solutions":["Always pass a base-10 integer offset query parameter, including 0: ?path=...&offset=0.","Coerce offsets with strconv/parseInt in client code before building the URL.","Strip units/fractions — send bytes as plain int64.","Use the official Nomad Go API client (AllocFS.ReadAt) instead of raw HTTP calls."],"exampleFix":"// before\nGET /v1/client/fs/readat?alloc-id=...&path=/alloc/logs/app.stdout.0\n// after\nGET /v1/client/fs/readat?alloc-id=...&path=/alloc/logs/app.stdout.0&offset=0&limit=100000","handlingStrategy":"validation","validationCode":"function buildReadAtURL(allocID, path, offset = 0, limit) {\n  if (!Number.isInteger(offset) || offset < 0) {\n    throw new TypeError(`offset must be a non-negative integer, got ${offset}`)\n  }\n  const q = new URLSearchParams({ 'alloc-id': allocID, path, offset: String(offset) })\n  if (limit != null) q.set('limit', String(limit))\n  return `/v1/client/fs/readat?${q}`\n}","typeGuard":"function isInt64(n) {\n  return Number.isInteger(n) && n >= 0 && n <= Number.MAX_SAFE_INTEGER\n}","tryCatchPattern":"resp, err := http.Get(u)\n// server-side response handling on caller:\nif strings.Contains(errMsg, \"error parsing offset\") {\n  retry with offset as plain base-10 integer string\n}","preventionTips":["Always include offset=0 explicitly, never omit it.","Send offsets as plain integers — no units, decimals, or formatting.","Prefer the official Nomad API client (AllocFS.ReadAt) over hand-built URLs.","Use the `limit` parameter for paging rather than computing offsets with units."],"tags":["filesystem","parsing","http-api"],"backgroundTag":"invalid-query-parameter","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"}