Skip to content

Intermittent 400 "invalid jti grant" after upgrading from box-java-sdk-gen to box-java-sdk:10.0.0 #2006

Description

@gcksean

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugAdded to issues that describes SDK bug

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions