{"record":{"id":"264a6280ba7bc971","repo":"VictoriaMetrics/VictoriaMetrics","slug":"cannot-read-accountid-w","errorCode":null,"errorMessage":"cannot read accountID: %w","messagePattern":"cannot read accountID: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/vmselectapi/server.go","lineNumber":360,"sourceCode":"\treturn n, nil\n}\n\nfunc (ctx *vmselectRequestCtx) readInt64() (int64, error) {\n\tctx.sizeBuf = bytesutil.ResizeNoCopyMayOverallocate(ctx.sizeBuf, 8)\n\tif _, err := io.ReadFull(ctx.bc, ctx.sizeBuf); err != nil {\n\t\tif err == io.EOF {\n\t\t\treturn 0, err\n\t\t}\n\t\treturn 0, fmt.Errorf(\"cannot read int64: %w\", err)\n\t}\n\tn := encoding.UnmarshalInt64(ctx.sizeBuf)\n\treturn n, nil\n}\n\nfunc (ctx *vmselectRequestCtx) readAccountIDProjectID() (uint32, uint32, error) {\n\taccountID, err := ctx.readUint32()\n\tif err != nil {\n\t\treturn 0, 0, fmt.Errorf(\"cannot read accountID: %w\", err)\n\t}\n\tprojectID, err := ctx.readUint32()\n\tif err != nil {\n\t\treturn 0, 0, fmt.Errorf(\"cannot read projectID: %w\", err)\n\t}\n\treturn accountID, projectID, nil\n}\n\n// maxSearchQuerySize is the maximum size of SearchQuery packet in bytes.\n// see https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5154#issuecomment-1757216612\nconst maxSearchQuerySize = 5 * 1024 * 1024\n\nfunc (ctx *vmselectRequestCtx) readSearchQuery() error {\n\tif err := ctx.readDataBufBytes(maxSearchQuerySize); err != nil {\n\t\treturn fmt.Errorf(\"cannot read searchQuery: %w\", err)\n\t}\n\ttail, err := ctx.sq.Unmarshal(ctx.dataBuf)\n\tif err != nil {","sourceCodeStart":342,"sourceCodeEnd":378,"githubUrl":"https://github.com/VictoriaMetrics/VictoriaMetrics/blob/5079fb58f1e8e62113f90c945ad71586c797d770/lib/vmselectapi/server.go#L342-L378","documentation":"Wrapping error from vmselectRequestCtx.readAccountIDProjectID when its first readUint32 call (accountID) fails. It chains the underlying error from reading the 4-byte accountID field. This means the tenant identifier at the start of the request packet could not be read — the stream was truncated or the connection broke.","triggerScenarios":"processTagValueSuffixes or processSeriesCount receives a packet shorter than the initial 4-byte accountID, or the connection errors while reading it.","commonSituations":"Clients omitting the accountID/projectID prefix required by the internal protocol (default single-tenant setups forgetting to write tenant IDs); truncated writes; dropped connections.","solutions":["Ensure the client writes accountID (4 bytes LE) as the first field of the request packet.","Verify network path stability between the caller and vmselect.","Check the wrapped error for the concrete cause.","Use /proc/<pid>/limits or connection logs to rule out abrupt disconnects; retry on new connection.","Align component versions."],"exampleFix":"// before (tenant prefix omitted)\nwriteSearchQuery(conn, sq)\n// after\nwriteUint32(conn, accountID)\nwriteUint32(conn, projectID)\nwriteSearchQuery(conn, sq)","handlingStrategy":"validation","validationCode":"// validate tenant prefix exists before sending packet\nif !packetHasTenantPrefix(buf) {\n    return errors.New(\"internal select requests must start with accountID+projectID\")\n}","typeGuard":null,"tryCatchPattern":"accountID, projectID, err := readAccountIDProjectID(conn)\nif err != nil {\n    return fmt.Errorf(\"tenant header read failed: %w\", err)\n}","preventionTips":["Always prefix internal protocol requests with accountID (4B LE) then projectID (4B LE), even in single-tenant mode","Verify partial writes: check n == len(buf) after conn.Write","Test against a real vmselect before deploying custom clients","Log the wrapped cause for every tenant-header failure"],"tags":["network","io","protocol","multitenancy"],"backgroundTag":"unexpected-eof-on-socket-read","analyzedSha":"5079fb58f1e8e62113f90c945ad71586c797d770","analyzedAt":"2026-09-03T18:10:26.153Z","contentChangedAt":"2026-09-03T18:10:26.153Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}