Description of the Issue
After upgrading from box-java-sdk-gen to v10 sdk
https://github.com/box/box-java-sdk#which-version-should-i-use
We are facing intermittent 400 errors which seem to be related to JWT token refresh for Get File Information calls: the exact method used is FilesManager#getFileById
I have also added analysis on the fix from our codebase side below, we used it as a workaround:
The intermittent 400 invalid_grant "A unique 'jti' value is required" is client-side retry of a non-idempotent token grant, specific to v10 because v10 added an automatic transport-retry layer (NetworkSession + BoxRetryStrategy, default maxAttempts=3) that our previous SDK (box-java-sdk-gen 0.7.0) did not have. When the first POST /oauth2/token attempt hits a transient failure (transport drop / 429 / 5xx) after Box has accepted and cached the jti, the SDK retries by re-sending the identical, already-signed JWT assertion — same one-time jti — which Box rejects. We reproduced it and confirmed the grant is triggered lazily during a getFileById call (BoxJWTAuth.retrieveToken → refreshToken → AuthorizationManager.requestAccessToken). Our fix is a RetryStrategy that never retries /oauth2/token or /oauth2/revoke.
Expected Behavior
Calls expected to go through as expected with old behaviour in box-java-sdk-gen
Error Message, Including Stack Trace
com.box.sdkgen.box.errors.BoxAPIError: Status 400; Request ID:
at com.box.sdkgen.box.errors.BoxAPIError$Builder.build(BoxAPIError.java:111) ~[box-java-sdk-10.16.1.jar:?]
at com.box.sdkgen.box.errors.BoxAPIError.fromAPICall(BoxAPIError.java:54) ~[box-java-sdk-10.16.1.jar:?]
at com.box.sdkgen.networking.boxnetworkclient.BoxNetworkClient.throwOnUnsuccessfulResponse(BoxNetworkClient.java:385) ~[box-java-sdk-10.16.1.jar:?]
at com.box.sdkgen.networking.boxnetworkclient.BoxNetworkClient.fetch(BoxNetworkClient.java:261) ~[box-java-sdk-10.16.1.jar:?]
at com.box.sdkgen.managers.authorization.AuthorizationManager.requestAccessToken(AuthorizationManager.java:126) ~[box-java-sdk-10.16.1.jar:?]
at com.box.sdkgen.managers.authorization.AuthorizationManager.requestAccessToken(AuthorizationManager.java:102) ~[box-java-sdk-10.16.1.jar:?]
at com.box.sdkgen.box.jwtauth.BoxJWTAuth.refreshToken(BoxJWTAuth.java:91) ~[box-java-sdk-10.16.1.jar:?]
at com.box.sdkgen.box.jwtauth.BoxJWTAuth.retrieveToken(BoxJWTAuth.java:120) ~[box-java-sdk-10.16.1.jar:?]
at com.box.sdkgen.box.jwtauth.BoxJWTAuth.retrieveAuthorizationHeader(BoxJWTAuth.java:132) ~[box-java-sdk-10.16.1.jar:?]
at com.box.sdkgen.networking.boxnetworkclient.BoxNetworkClient.prepareHeaders(BoxNetworkClient.java:298) ~[box-java-sdk-10.16.1.jar:?]
at com.box.sdkgen.networking.boxnetworkclient.BoxNetworkClient.prepareRequest(BoxNetworkClient.java:274) ~[box-java-sdk-10.16.1.jar:?]
at com.box.sdkgen.networking.boxnetworkclient.BoxNetworkClient.fetch(BoxNetworkClient.java:156) ~[box-java-sdk-10.16.1.jar:?]
at com.box.sdkgen.managers.files.FilesManager.getFileById(FilesManager.java:98) ~[box-java-sdk-10.16.1.jar:?]
at com.box.sdkgen.managers.files.FilesManager.getFileById_aroundBody2(FilesManager.java:57) ~[box-java-sdk-10.16.1.jar:?]
at com.box.sdkgen.managers.files.FilesManager$AjcClosure3.run(FilesManager.java:1) ~[box-java-sdk-10.16.1.jar:?]
at org.aspectj.runtime.reflect.JoinPointImpl.proceed(JoinPointImpl.java:164) ~[aspectjweaver-1.9.24.jar:?]
at com.apple.aml.kobe.document_service.box.account_pool.BoxManagerAspect.lambda$executeWithResilience$0(BoxManagerAspect.java:137) ~[main/:?]
at io.github.resilience4j.circuitbreaker.CircuitBreaker.lambda$decorateSupplier$5(CircuitBreaker.java:194) ~[resilience4j-circuitbreaker-2.2.0.jar:2.2.0]
at io.github.resilience4j.circuitbreaker.CircuitBreaker.executeSupplier(CircuitBreaker.java:651) ~[resilience4j-circuitbreaker-2.2.0.jar:2.2.0]
at com.apple.aml.kobe.document_service.box.account_pool.BoxManagerAspect.executeWithResilience(BoxManagerAspect.java:149) ~[main/:?]
at com.apple.aml.kobe.document_service.box.account_pool.BoxManagerAspect.ajc$inlineAccessMethod$com_apple_aml_kobe_document_service_box_account_pool_BoxManagerAspect$com_apple_aml_kobe_document_service_box_account_pool_BoxManagerAspect$executeWithResilience(BoxManagerAspect.java:1) ~[main/:?]
at com.apple.aml.kobe.document_service.box.account_pool.BoxManagerAspect.interceptBoxManagerMethods(BoxManagerAspect.java:61) ~[main/:?]
at com.box.sdkgen.managers.files.FilesManager.getFileById(FilesManager.java:57) ~[box-java-sdk-10.16.1.jar:?]
at com.apple.aml.kobe.document_service.box.service.BoxConnectorService.getFileInfo(BoxConnectorService.java:487) ~[main/:?]
at com.apple.aml.kobe.document_service.box.service.BoxConnectorService.getFileInfo(BoxConnectorService.java:453) ~[main/:?]
at com.apple.aml.kobe.document_service.box.BoxConnectorController.getFileInfo(BoxConnectorController.java:435) ~[main/:?]
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) ~[?:?]
at java.base/java.lang.reflect.Method.invoke(Method.java:565) ~[?:?]
at org.springframework.web.reactive.result.method.InvocableHandlerMethod.lambda$invoke$0(InvocableHandlerMethod.java:208) ~[spring-webflux-6.2.11.jar:6.2.11]
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:132) ~[reactor-core-3.7.11.jar:3.7.11]
at reactor.core.publisher.MonoPublishOn$PublishOnSubscriber.run(MonoPublishOn.java:181) ~[reactor-core-3.7.11.jar:3.7.11]
at io.micrometer.context.ContextSnapshot.lambda$wrap$0(ContextSnapshot.java:91) ~[context-propagation-1.1.3.jar:1.1.3]
at reactor.core.scheduler.ExecutorScheduler$ExecutorPlainRunnable.run(ExecutorScheduler.java:135) ~[reactor-core-3.7.11.jar:3.7.11]
at java.base/java.lang.VirtualThread.run(VirtualThread.java:456) ~[?:?]
An example token-call request_id for one captured on a reproduced failure:
• BOX-REQUEST-ID: 04ac485729dc58d74a16444fee77e3391
• Endpoint: POST https://api.box.com/oauth2/token
• Timestamp: 2026-09-18T03:40:43.289Z (UTC)
• Response body: {"error":"invalid_grant","error_description":"Please check the 'jti' claim. A unique 'jti' value is required."}
Versions Used
v10
Description of the Issue
After upgrading from box-java-sdk-gen to v10 sdk
https://github.com/box/box-java-sdk#which-version-should-i-use
We are facing intermittent 400 errors which seem to be related to JWT token refresh for Get File Information calls: the exact method used is FilesManager#getFileById
I have also added analysis on the fix from our codebase side below, we used it as a workaround:
The intermittent 400 invalid_grant "A unique 'jti' value is required" is client-side retry of a non-idempotent token grant, specific to v10 because v10 added an automatic transport-retry layer (NetworkSession + BoxRetryStrategy, default maxAttempts=3) that our previous SDK (box-java-sdk-gen 0.7.0) did not have. When the first POST /oauth2/token attempt hits a transient failure (transport drop / 429 / 5xx) after Box has accepted and cached the jti, the SDK retries by re-sending the identical, already-signed JWT assertion — same one-time jti — which Box rejects. We reproduced it and confirmed the grant is triggered lazily during a getFileById call (BoxJWTAuth.retrieveToken → refreshToken → AuthorizationManager.requestAccessToken). Our fix is a RetryStrategy that never retries /oauth2/token or /oauth2/revoke.
Expected Behavior
Calls expected to go through as expected with old behaviour in box-java-sdk-gen
Error Message, Including Stack Trace
An example token-call request_id for one captured on a reproduced failure:
• BOX-REQUEST-ID: 04ac485729dc58d74a16444fee77e3391
• Endpoint: POST https://api.box.com/oauth2/token
• Timestamp: 2026-09-18T03:40:43.289Z (UTC)
• Response body: {"error":"invalid_grant","error_description":"Please check the 'jti' claim. A unique 'jti' value is required."}
Versions Used
v10