{"record":{"id":"171863052953f414","repo":"elastic/elasticsearch","slug":"must-be-non-negative-got","errorCode":null,"errorMessage":"{} must be non-negative, got [{}]","messagePattern":"(.+?) must be non-negative, got \\[(.+?)\\]","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"libs/gpu-codec/src/main/java/org/elasticsearch/gpu/CuVSGPUSupport.java","lineNumber":49,"sourceCode":"\n    private CuVSGPUSupport() {}\n\n    private record GpuInfo(long totalMemory, String name) {\n\n        static final GpuInfo UNSUPPORTED = new GpuInfo(0L, null);\n\n        GpuInfo {\n            checkNonNegative(totalMemory, \"totalMemory\");\n        }\n    }\n\n    public static GPUSupport instance() {\n        return INSTANCE;\n    }\n\n    static void checkNonNegative(long value, String name) {\n        if (value < 0) {\n            throw new IllegalArgumentException(name + \" must be non-negative, got [\" + value + \"]\");\n        }\n    }\n\n    private static class Holder {\n        static final GpuInfo GPU_INFO = initializeGpuInfo();\n    }\n\n    /**\n     * Initializes GPU support information by finding the first compatible GPU.\n     * Returns a {@link GpuInfo} with memory and name, or {@link GpuInfo#UNSUPPORTED} if no compatible GPU is found.\n     */\n    private static GpuInfo initializeGpuInfo() {\n        try {\n            var gpuInfoProvider = CuVSProvider.provider().gpuInfoProvider();\n            LOG.info(\"Initializing GPU support with CuVS provider {}\", gpuInfoProvider.getClass().getName());\n            var availableGPUs = gpuInfoProvider.availableGPUs();\n            if (availableGPUs.isEmpty()) {\n                LOG.warn(\"No GPU found\");","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/gpu-codec/src/main/java/org/elasticsearch/gpu/CuVSGPUSupport.java#L31-L67","documentation":"Thrown by CuVSGPUSupport.checkNonNegative when a GpuInfo record is constructed with a negative totalMemory value. GpuInfo is a record whose compact constructor calls checkNonNegative(totalMemory, \"totalMemory\"), enforcing the invariant that reported GPU total memory cannot be negative.","triggerScenarios":"Constructing a GpuInfo with totalMemory < 0, or a code path that initializes GpuInfo from a query (e.g., a CUDA/FFI call) returning a sentinel negative value when the GPU query fails. The record's compact constructor runs the check at construction time.","commonSituations":"A GPU detection/query routine returning -1 or another negative sentinel on failure (driver missing, device unavailable); unit tests constructing GpuInfo with bogus values; an FFI binding returning an error code that is misinterpreted as a memory size.","solutions":["Inspect the source of the totalMemory value: if it comes from a GPU query that can fail, handle the failure sentinel (e.g., -1) before constructing GpuInfo.","If no compatible GPU is available, use GpuInfo.UNSUPPORTED rather than constructing with a negative memory value.","In tests, use realistic non-negative memory values or the UNSUPPORTED constant."],"exampleFix":"// before: passing a negative sentinel from a failed query\nlong mem = queryTotalMemory(); // returns -1 on failure\nGpuInfo info = new GpuInfo(mem, name); // throws\n\n// after: guard the query result\nlong mem = queryTotalMemory();\nif (mem < 0) {\n    return GpuInfo.UNSUPPORTED;\n}\nGpuInfo info = new GpuInfo(mem, name);","handlingStrategy":"validation","validationCode":"static GpuInfo safeGpuInfo(long totalMemory, String name) {\n    if (totalMemory < 0) {\n        return GpuInfo.UNSUPPORTED;\n    }\n    return new GpuInfo(totalMemory, name);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Handle negative sentinels from GPU queries before constructing GpuInfo.","Use GpuInfo.UNSUPPORTED when no GPU is available.","In tests, use realistic non-negative memory values."],"tags":["gpu","validation","elasticsearch","codec","initialization"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:17:08.281Z"}