{"record":{"id":"02f4f27f6787759d","repo":"junit-team/junit5","slug":"thread-mode-must-not-be-inferred","errorCode":null,"errorMessage":"thread mode must not be INFERRED","messagePattern":"thread mode must not be INFERRED","errorType":"exception","errorClass":"PreconditionViolationException","httpStatus":null,"severity":"error","filePath":"junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutInvocationFactory.java","lineNumber":43,"sourceCode":"/**\n * @since 5.9\n */\nclass TimeoutInvocationFactory {\n\n\tprivate final Store store;\n\n\tTimeoutInvocationFactory(Store store) {\n\t\tthis.store = Preconditions.notNull(store, \"store must not be null\");\n\t}\n\n\t<T extends @Nullable Object> Invocation<T> create(ThreadMode threadMode,\n\t\t\tTimeoutInvocationParameters<T> parameters) {\n\t\tPreconditions.notNull(parameters, \"timeout invocation parameters must not be null\");\n\t\treturn switch (Preconditions.notNull(threadMode, \"thread mode must not be null\")) {\n\t\t\tcase SAME_THREAD -> new SameThreadTimeoutInvocation<>(parameters,\n\t\t\t\tgetThreadExecutorForSameThreadInvocation());\n\t\t\tcase SEPARATE_THREAD -> new SeparateThreadTimeoutInvocation<>(parameters);\n\t\t\tcase INFERRED -> throw new PreconditionViolationException(\"thread mode must not be INFERRED\");\n\t\t};\n\t}\n\n\t@SuppressWarnings(\"resource\")\n\tprivate ScheduledExecutorService getThreadExecutorForSameThreadInvocation() {\n\t\treturn store.computeIfAbsent(SingleThreadExecutorResource.class).get();\n\t}\n\n\t@SuppressWarnings({ \"deprecation\", \"try\" })\n\tabstract static class ExecutorResource implements Store.CloseableResource, AutoCloseable {\n\n\t\tprivate final ScheduledExecutorService executor;\n\n\t\tExecutorResource(ScheduledExecutorService executor) {\n\t\t\tthis.executor = executor;\n\t\t}\n\n\t\tScheduledExecutorService get() {","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/junit-team/junit5/blob/f070c699a08b5d8393df9afd147af5c5e90bb21b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutInvocationFactory.java#L25-L61","documentation":"Thrown when TimeoutInvocationFactory.create() receives ThreadMode.INFERRED. INFERRED is a sentinel value that the JUnit engine resolves to either SAME_THREAD or SEPARATE_THREAD before reaching the factory — so passing INFERRED directly is an internal contract violation, not a user configuration error. This indicates a bug in the engine's internal dispatch logic or a custom extension that bypassed the resolution step.","triggerScenarios":"Calling TimeoutInvocationFactory.create(ThreadMode.INFERRED, parameters) directly. This should not be reachable through normal @Timeout usage because the engine resolves INFERRED upstream. A custom extension that programmatically invokes the factory with an unresolved ThreadMode could trigger it.","commonSituations":"Essentially unreachable in normal usage. Would only appear if a custom extension or engine modification incorrectly passes ThreadMode.INFERRED to the factory without resolving it first. Developers writing extensions that interact with the timeout machinery may encounter this during development.","solutions":["Do not pass ThreadMode.INFERRED to create() — resolve it to SAME_THREAD or SEPARATE_THREAD first","If you are writing a custom extension, use the engine's ThreadMode resolution logic before calling the factory","Report as a JUnit bug if encountered through standard @Timeout annotations without custom extensions"],"exampleFix":"// before (incorrect direct call)\nfactory.create(ThreadMode.INFERRED, parameters);\n\n// after (resolve to concrete mode first)\nThreadMode resolved = determineThreadMode(); // SAME_THREAD or SEPARATE_THREAD\nfactory.create(resolved, parameters);","handlingStrategy":"validation","validationCode":"// Guard against passing INFERRED to the factory (internal use only)\nimport org.junit.jupiter.engine.extension.TimeoutInvocationFactory;\nimport org.junit.jupiter.api.Timeout.ThreadMode;\n\nThreadMode safeMode = (threadMode == ThreadMode.INFERRED) ? ThreadMode.SAME_THREAD : threadMode;\nfactory.create(safeMode, parameters);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never pass ThreadMode.INFERRED directly to internal factory methods — always resolve it to SAME_THREAD or SEPARATE_THREAD first","This error indicates an internal bug — report it to the JUnit team if encountered without custom extensions"],"tags":["timeout","internal","precondition","junit-jupiter"],"backgroundTag":null,"analyzedSha":"f070c699a08b5d8393df9afd147af5c5e90bb21b","analyzedAt":"2026-08-11T20:31:00.530Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}