Skip to content

FINERACT-2738: Add warning when Idempotency-Key header is missing (config-gated) - #6228

Open
AshharAhmadKhan wants to merge 1 commit into
apache:developfrom
AshharAhmadKhan:FINERACT-2738-Add-warning-when-Idempotency-Key-header-is-missing
Open

FINERACT-2738: Add warning when Idempotency-Key header is missing (config-gated)#6228
AshharAhmadKhan wants to merge 1 commit into
apache:developfrom
AshharAhmadKhan:FINERACT-2738-Add-warning-when-Idempotency-Key-header-is-missing

Conversation

@AshharAhmadKhan

Copy link
Copy Markdown
Contributor

JIRA
https://issues.apache.org/jira/browse/FINERACT-2738

Problem
When the Idempotency-Key header is missing on a request, it is processed silently. No log, no signal, no observability. This creates a risk of unintended duplicate command processing going unnoticed.

This was originally raised in FINERACT-2591, and an earlier attempt (PR #5873) implemented unconditional WARN logging. That approach was rejected in review, since it would spam logs for every client that does not use idempotency handling.

Fix
Added a new global configuration option, enable-idempotency-validation, disabled by default for backward compatibility.

When enabled, a WARN level log is emitted if the Idempotency-Key header is missing on a request. The flag is read through the cached global configuration service (ConfigurationDomainService), following the same pattern used elsewhere in the codebase.

No existing request processing behavior changes. This is observability only, and off by default.

Testing
Added IdempotencyStoreFilterTest covering all four branches: validation disabled, content type not allowed, header present, and header missing with validation enabled.

@AshharAhmadKhan

Copy link
Copy Markdown
Contributor Author

hey @adamsaghy , please trigger checks whenever you are free please.

@AshharAhmadKhan
AshharAhmadKhan force-pushed the FINERACT-2738-Add-warning-when-Idempotency-Key-header-is-missing branch from 89fd28d to 52d06a6 Compare August 5, 2026 09:20
@AshharAhmadKhan

Copy link
Copy Markdown
Contributor Author

hey @adamsaghy , failures looks flaky. Can you please retrigger checks when you get a chance, thankss.

@AshharAhmadKhan

Copy link
Copy Markdown
Contributor Author

Hey @adamsaghy , I checked the failures again after the retrigger.

These are unrelated to my changes. The OAuth2AuthenticationTest is failing on Shard 2, and this is nowhere related to my PR.

Should we wait before retriggering, or is there something I'm missing here?

@adamsaghy

Copy link
Copy Markdown
Contributor

@AshharAhmadKhan When were you rebased this PR with latest develop branch?

@adamsaghy

adamsaghy commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Based on the logs, there is no tenant context available when the idempotency filter is called:

fineract-1    | 2026-08-05T11:14:39.056124961Z 
fineract-1    | 2026-08-05T11:14:39.056128446Z org.springframework.expression.spel.SpelEvaluationException: EL1011E: Method call: Attempted to call method getTenantIdentifier() on null context object
fineract-1    | 2026-08-05T11:14:39.056131360Z 	at org.springframework.expression.spel.ast.MethodReference.throwIfNotNullSafe(MethodReference.java:169)
fineract-1    | 2026-08-05T11:14:39.056134685Z 	at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:118)
fineract-1    | 2026-08-05T11:14:39.056137279Z 	at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:108)
fineract-1    | 2026-08-05T11:14:39.056139832Z 	at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:66)
fineract-1    | 2026-08-05T11:14:39.056142276Z 	at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:96)
fineract-1    | 2026-08-05T11:14:39.056144760Z 	at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:116)
fineract-1    | 2026-08-05T11:14:39.056156497Z 	at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:273)
fineract-1    | 2026-08-05T11:14:39.056163217Z 	at org.springframework.cache.interceptor.CacheOperationExpressionEvaluator.key(CacheOperationExpressionEvaluator.java:106)
fineract-1    | 2026-08-05T11:14:39.056167503Z 	at org.springframework.cache.interceptor.CacheAspectSupport$CacheOperationContext.generateKey(CacheAspectSupport.java:971)
fineract-1    | 2026-08-05T11:14:39.056171208Z 	at org.springframework.cache.interceptor.CacheAspectSupport.generateKey(CacheAspectSupport.java:761)
fineract-1    | 2026-08-05T11:14:39.056174884Z 	at org.springframework.cache.interceptor.CacheAspectSupport.findCachedValue(CacheAspectSupport.java:524)
fineract-1    | 2026-08-05T11:14:39.056178950Z 	at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:448)
fineract-1    | 2026-08-05T11:14:39.056182595Z 	at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:412)
fineract-1    | 2026-08-05T11:14:39.056186391Z 	at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:65)
fineract-1    | 2026-08-05T11:14:39.056189966Z 	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
fineract-1    | 2026-08-05T11:14:39.056194923Z 	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:728)
fineract-1    | 2026-08-05T11:14:39.056198759Z 	at org.apache.fineract.infrastructure.configuration.domain.GlobalConfigurationRepositoryWrapper$$SpringCGLIB$$1.findOneByNameWithNotFoundDetection(<generated>)
fineract-1    | 2026-08-05T11:14:39.056203055Z 	at org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainServiceJpa.getGlobalConfigurationPropertyData(ConfigurationDomainServiceJpa.java:392)
fineract-1    | 2026-08-05T11:14:39.056206480Z 	at org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainServiceJpa.isIdempotencyValidationEnabled(ConfigurationDomainServiceJpa.java:604)
fineract-1    | 2026-08-05T11:14:39.056210356Z 	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
fineract-1    | 2026-08-05T11:14:39.056214021Z 	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
fineract-1    | 2026-08-05T11:14:39.056217326Z 	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:360)
fineract-1    | 2026-08-05T11:14:39.056220531Z 	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:724)
fineract-1    | 2026-08-05T11:14:39.056224116Z 	at org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainServiceJpa$$SpringCGLIB$$0.isIdempotencyValidationEnabled(<generated>)
fineract-1    | 2026-08-05T11:14:39.056227842Z 	at org.apache.fineract.infrastructure.core.filters.IdempotencyStoreFilter.warnIfIdempotencyKeyHeaderMissing(IdempotencyStoreFilter.java:76)
fineract-1    | 2026-08-05T11:14:39.056231427Z 	at org.apache.fineract.infrastructure.core.filters.IdempotencyStoreFilter.doFilterInternal(IdempotencyStoreFilter.java:53)
fineract-1    | 2026-08-05T11:14:39.056235202Z 	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)

@AshharAhmadKhan
AshharAhmadKhan force-pushed the FINERACT-2738-Add-warning-when-Idempotency-Key-header-is-missing branch from 52d06a6 to 77578cf Compare August 5, 2026 14:26
@AshharAhmadKhan

Copy link
Copy Markdown
Contributor Author

Thanks a lot @adamsaghy for your guidance, please let me know if you need any more changes. Thanks again.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants