{"record":{"id":"b2c391ef3c15f8ea","repo":"jwtk/jjwt","slug":"both-content-and-claims-cannot-be-specified-c","errorCode":null,"errorMessage":"Both 'content' and 'claims' cannot be specified. Choose either one.","messagePattern":"Both 'content' and 'claims' cannot be specified\\. Choose either one\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtBuilder.java","lineNumber":496,"sourceCode":"    public String compact() {\n\n        final boolean jwe = this.enc != null;\n\n        if (jwe && signFunction != null) {\n            String msg = \"Both 'signWith' and 'encryptWith' cannot be specified. Choose either one.\";\n            throw new IllegalStateException(msg);\n        }\n\n        Payload payload = Assert.stateNotNull(this.payload, \"Payload instance null, internal error\");\n        final Claims claims = this.claimsBuilder.build();\n\n        if (jwe && payload.isEmpty() && Collections.isEmpty(claims)) { // JWE payload can never be empty:\n            String msg = \"Encrypted JWTs must have either 'claims' or non-empty 'content'.\";\n            throw new IllegalStateException(msg);\n        } // otherwise JWS and Unprotected JWT payloads can be empty\n\n        if (!payload.isEmpty() && !Collections.isEmpty(claims)) {\n            throw new IllegalStateException(\"Both 'content' and 'claims' cannot be specified. Choose either one.\");\n        }\n\n        if (this.serializer == null) { // try to find one based on the services available\n            //noinspection unchecked\n            json(Services.get(Serializer.class));\n        }\n\n        if (!Collections.isEmpty(claims)) { // normalize so we have one object to deal with:\n            payload = new Payload(claims);\n        }\n        if (compressionAlgorithm != null && !payload.isEmpty()) {\n            payload.setZip(compressionAlgorithm);\n            this.headerBuilder.put(DefaultHeader.COMPRESSION_ALGORITHM.getId(), compressionAlgorithm.getId());\n        }\n\n        if (Strings.hasText(payload.getContentType())) {\n            // We retain the value from the content* calls to prevent accidental removal from\n            // header().empty() or header().delete calls","sourceCodeStart":478,"sourceCodeEnd":514,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtBuilder.java#L478-L514","documentation":"This error is thrown by DefaultJwtBuilder.compact() when a caller has set both raw content (e.g. setContent(...)) and claims (e.g. setClaims(...)) on the builder. A JWT can have exactly one payload representation — either opaque string/byte content or a claims JSON object — so specifying both is ambiguous and rejected with an IllegalStateException before serialization.","triggerScenarios":"Calling JwtBuilder.setContent()/setContentInputStream() and then setClaims()/claim() (or vice versa) on the same builder instance before compact(). Also happens when a builder is reused: claims set in one code path plus content set in another.","commonSituations":"Reusing a shared builder across methods; migrating code from content-based JWS to claims-based JWS while leaving the old setContent call in place; framework code that always calls claim(...) on a builder the user already populated with content.","solutions":["Remove either the setContent(...) call or the setClaims(...)/claim(...) calls so only one payload source remains","If reusing a builder, create a fresh builder per token (Jwts.builder()) instead of resetting fields","Use claim() for standard business-logic tokens; use setContent() only for opaque/non-JSON payloads, never both"],"exampleFix":"// before\nString jwt = Jwts.builder()\n    .setContent(\"raw-payload\")\n    .claim(\"sub\", \"user\")\n    .compact();\n// after\nString jwt = Jwts.builder()\n    .claim(\"sub\", \"user\")\n    .compact();","handlingStrategy":"validation","validationCode":"if (content != null && claims != null) {\n    throw new IllegalArgumentException(\"Set either content or claims, not both\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    String jwt = builder.compact();\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"Both 'content' and 'claims'\")) {\n        throw new TokenBuildException(\"Conflicting payload configuration\", e);\n    }\n    throw e;\n}","preventionTips":["Use a fresh Jwts.builder() per token instead of reusing instances","Decide per token type whether it is content-based or claims-based and enforce in a wrapper method","Avoid wrapper APIs that call both setContent and claim on the same builder"],"tags":["jwt","builder","api-misuse"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"fb71496164c71442d08adec4571d9616ed5e1b8d","analyzedAt":"2026-09-09T00:33:09.982Z","contentChangedAt":"2026-09-09T00:33:09.982Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}