{"record":{"id":"c3a96bc488bcf660","repo":"quarkusio/quarkus","slug":"string-too-large-to-record-param","errorCode":null,"errorMessage":"String too large to record: ${param}","messagePattern":"String too large to record: (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"core/deployment/src/main/java/io/quarkus/deployment/recording/BytecodeRecorderImpl.java","lineNumber":697,"sourceCode":"                    ResultHandle createValue(MethodContext context, MethodCreator method, ResultHandle array) {\n                        // If the value is a proxy, it may be non-null at build time but become null\n                        // when we actually create the value during initialization;\n                        // so we need to use 'ofNullable' and not 'of' here.\n                        return method.invokeStaticMethod(ofMethod(Optional.class, \"ofNullable\", Optional.class, Object.class),\n                                context.loadDeferred(res));\n                    }\n                };\n            } else {\n                return new DeferredArrayStoreParameter(param, expectedType) {\n                    @Override\n                    ResultHandle createValue(MethodContext context, MethodCreator method, ResultHandle array) {\n                        return method.invokeStaticMethod(ofMethod(Optional.class, \"empty\", Optional.class));\n                    }\n                };\n            }\n        } else if (param instanceof String) {\n            if (((String) param).length() > 65535) {\n                throw new RuntimeException(\"String too large to record: \" + param);\n            }\n            return new DeferredParameter() {\n                @Override\n                ResultHandle doLoad(MethodContext context, MethodCreator method, ResultHandle array) {\n                    return method.load((String) param);\n                }\n            };\n        } else if (param instanceof URL) {\n            String url = ((URL) param).toExternalForm();\n            return new DeferredParameter() {\n                @Override\n                ResultHandle doLoad(MethodContext context, MethodCreator method, ResultHandle array) {\n                    AssignableResultHandle value = method.createVariable(URL.class);\n                    try (TryBlock et = method.tryBlock()) {\n                        et.assign(value, et.newInstance(MethodDescriptor.ofConstructor(URL.class, String.class), et.load(url)));\n                        try (CatchBlockCreator malformed = et.addCatch(MalformedURLException.class)) {\n                            malformed.throwException(RuntimeException.class, \"Malformed URL\", malformed.getCaughtException());\n                        }","sourceCodeStart":679,"sourceCodeEnd":715,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/core/deployment/src/main/java/io/quarkus/deployment/recording/BytecodeRecorderImpl.java#L679-L715","documentation":"Recorded String parameters are emitted as JVM ldc constants, which are limited to 65535 UTF-8 bytes by the class file format. Quarkus rejects any String longer than that at recording time because it could not produce valid bytecode for it.","triggerScenarios":"Passing a String argument longer than 65535 characters to a recorder method — e.g. embedded JSON, base64 blobs, generated SQL, PEM/keystore content, or a whole template body.","commonSituations":"Embedding a large certificate/keystore or serialized payload via a recorder; config values that ballooned; tests generating very large strings; setting schema/index definitions as a single recorded string.","solutions":["Do not pass the large string through the recorder; write it to a file at build time and pass the file path, loading contents at runtime","Store the data as a classpath resource and read it from the runtime code instead of recording it","Chunk the string into pieces under 65535 chars and reassemble in the recorder/runtime, though resource approach is preferred","Compress the payload (e.g. base64 of gzip) only if it then fits under the limit","If this comes from a config value, reduce the value size or move it out of recorded configuration"],"exampleFix":"// before: huge string via recorder\nrecorder.setSchema(hugeSchemaJson);\n// after: write to file at build time, pass path\nPath p = generatedResourcesDir.resolve(\"schema.json\");\nFiles.writeString(p, hugeSchemaJson);\nrecorder.setSchemaLocation(p.toString());","handlingStrategy":"validation","validationCode":"if (value != null && value.length() > 65535) {\n    throw new IllegalArgumentException(\n        \"Value exceeds JVM constant-pool limit (65535); pass a resource path instead: \" + value.length());\n}\nrecorder.setValue(value);","typeGuard":"static boolean isRecordableString(String s) {\n    return s == null || s.length() <= 65535;\n}","tryCatchPattern":"try {\n    recorder.setValue(largeString);\n} catch (RuntimeException e) {\n    if (e.getMessage().startsWith(\"String too large\")) {\n        Path f = outDir.resolve(\"payload.txt\");\n        Files.writeString(f, largeString);\n        recorder.setValueFromFile(f.toString());\n    } else { throw e; }\n}","preventionTips":["Check String lengths before passing to recorders","Write large payloads to build-time resources and pass paths","Keep embedded config/schema text under 64KB or externalize it"],"tags":["quarkus","build-time","recorder","jvm-limit","string"],"backgroundTag":"string-too-large-for-constant-pool","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}