{"record":{"id":"f2f228444585d08a","repo":"hashicorp/nomad","slug":"invalid-starting-token-q-v","errorCode":null,"errorMessage":"invalid starting token %q: %v","messagePattern":"invalid starting token %q: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/csi/client.go","lineNumber":482,"sourceCode":"\treturn NewCreateVolumeResponse(resp), nil\n}\n\nfunc (c *client) ControllerListVolumes(ctx context.Context, req *ControllerListVolumesRequest, opts ...grpc.CallOption) (*ControllerListVolumesResponse, error) {\n\tif err := c.ensureConnected(ctx); err != nil {\n\t\treturn nil, err\n\t}\n\n\terr := req.Validate()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcreq := req.ToCSIRepresentation()\n\tresp, err := c.controllerClient.ListVolumes(ctx, creq, opts...)\n\tif err != nil {\n\t\tcode := status.Code(err)\n\t\tswitch code {\n\t\tcase codes.Aborted:\n\t\t\treturn nil, fmt.Errorf(\n\t\t\t\t\"invalid starting token %q: %v\", req.StartingToken, err)\n\t\tcase codes.Internal:\n\t\t\treturn nil, fmt.Errorf(\n\t\t\t\t\"controller plugin returned an internal error, check the plugin allocation logs for more information: %v\", err)\n\t\t}\n\t\treturn nil, err\n\t}\n\treturn NewListVolumesResponse(resp), nil\n}\n\nfunc (c *client) ControllerDeleteVolume(ctx context.Context, req *ControllerDeleteVolumeRequest, opts ...grpc.CallOption) error {\n\tif err := c.ensureConnected(ctx); err != nil {\n\t\treturn err\n\t}\n\n\terr := req.Validate()\n\tif err != nil {\n\t\treturn err","sourceCodeStart":464,"sourceCodeEnd":500,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/plugins/csi/client.go#L464-L500","documentation":"ControllerListVolumes got gRPC code Aborted from the CSI plugin, which per the CSI spec means the pagination StartingToken is invalid — expired, malformed, or belonging to a different enumeration session. Nomad wraps it as \"invalid starting token\" using req.StartingToken.","triggerScenarios":"Calling ControllerListVolumes with a request whose StartingToken is stale or corrupted — e.g. resuming a listing after the plugin restarted, using a token from a different plugin, or a client that cached the token too long.","commonSituations":"Long-running external tool paginating volumes with delays between pages; plugin restart or failover invalidated in-memory pagination state; token copy/paste error; mixing plugins (token from vendor A used against vendor B).","solutions":["Retry the list without a starting token to enumerate volumes from the beginning.","Re-run the pagination loop in one pass without long delays between pages.","If pagination repeatedly fails, list all pages and paginate client-side instead of persisting tokens.","Check whether the plugin restarted between calls; restart your pagination with a fresh token."],"exampleFix":"// before (reusing stale token)\nresp, err := client.ListVolumes(ctx, &csi.ListVolumesRequest{StartingToken: oldToken})\n// after (fresh listing)\nresp, err := client.ListVolumes(ctx, &csi.ListVolumesRequest{})","handlingStrategy":"fallback","validationCode":"// Don't persist tokens across plugin restarts or long periods\nif tokenAge(startingToken) > maxTokenTTL {\n    startingToken = \"\" // restart listing from the first page\n}","typeGuard":null,"tryCatchPattern":"resp, err := client.ControllerListVolumes(ctx, req)\nif err != nil && strings.Contains(err.Error(), \"invalid starting token\") {\n    req.StartingToken = \"\"\n    resp, err = client.ControllerListVolumes(ctx, req) // restart from page 1\n}","preventionTips":["Complete pagination in one pass without long delays.","Discard tokens after any plugin restart or client restart.","On Aborted, always restart listing from the beginning rather than failing."],"tags":["csi","grpc","pagination","list-volumes"],"backgroundTag":"invalid-pagination-token","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}