{"record":{"id":"9c30e92843d986c4","repo":"apache/beam","slug":"value-only-available-at-runtime-but-accessed-from-a-non","errorCode":null,"errorMessage":"Value only available at runtime, but accessed from a non-runtime context: <provider>","messagePattern":"Value only available at runtime, but accessed from a non-runtime context: <provider>","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/options/ValueProvider.java","lineNumber":255,"sourceCode":"      this.propertyName = propertyName;\n      this.klass = klass;\n      this.defaultValue = defaultValue;\n      this.optionsId = optionsId;\n    }\n\n    /**\n     * Once set, all {@code RuntimeValueProviders} will return {@code true} from {@code\n     * isAccessible()}. By default, the value is set when deserializing {@link PipelineOptions}.\n     */\n    static void setRuntimeOptions(PipelineOptions runtimeOptions) {\n      optionsMap.put(runtimeOptions.getOptionsId(), runtimeOptions);\n    }\n\n    @Override\n    public T get() {\n      PipelineOptions options = optionsMap.get(optionsId);\n      if (options == null) {\n        throw new IllegalStateException(\n            \"Value only available at runtime, but accessed from a non-runtime context: \" + this);\n      }\n      try {\n        Method method = klass.getMethod(methodName);\n        PipelineOptions methodOptions = options.as(klass);\n        InvocationHandler handler = Proxy.getInvocationHandler(methodOptions);\n        @SuppressWarnings(\"unchecked\")\n        ValueProvider<T> result = (ValueProvider<T>) handler.invoke(methodOptions, method, null);\n        // Two cases: If we have deserialized a new value from JSON, it will\n        // be wrapped in a StaticValueProvider, which we can provide here. If\n        // not, there was no JSON value, and we return the default, whether or\n        // not it is null.\n        if (result instanceof StaticValueProvider) {\n          return result.get();\n        }\n        return defaultValue;\n      } catch (OutOfMemoryError oom) {\n        throw oom;","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/options/ValueProvider.java#L237-L273","documentation":"RuntimeValueProvider.get() reads the PipelineOptions captured at runtime execution time from an internal optionsMap keyed by optionsId. This IllegalStateException is thrown when get() is called outside the runtime worker context (no options registered), meaning the value is unavailable at the current point of the pipeline lifecycle.","triggerScenarios":"Calling get() (directly or indirectly via toString()) on a RuntimeValueProvider during graph construction/driver-side code instead of inside a DoFn/worker where options have been bound.","commonSituations":"Logging a value provider at pipeline-build time, accessing a runtime option in a constructor or @Setup-adjacent driver code, or calling get() in a unit test without simulating runtime options.","solutions":["Move the get() call into runtime code (DoFn.processElement/@Setup on the worker)","Check isAccessible() before calling get() and handle the driver-side case (use defaultValue or serialize the provider instead)","In tests, use the test utilities that install runtime options (e.g. TestValueProvider or call valueProvider.setTestOptions-like helpers)"],"exampleFix":"// before\nLOG.info(\"value is \" + provider.get()); // throws at graph-build time\n// after\nif (provider.isAccessible()) { LOG.info(\"value is \" + provider.get()); }\nelse { LOG.info(\"value resolved at runtime\"); }","handlingStrategy":"type-guard","validationCode":"if (!provider.isAccessible()) { /* not yet in runtime context: defer or use default */ }","typeGuard":"boolean usableNow(RuntimeValueProvider<?> p) { return p.isAccessible(); }","tryCatchPattern":"try { v = provider.get(); } catch (IllegalStateException e) { v = defaultValue; /* driver-side fallback */ }","preventionTips":["Never call get() during pipeline construction; use isAccessible() to check","Read runtime options only inside DoFn methods or other worker-side code","In tests, install test options so providers are accessible before asserting on values"],"tags":["java","apache-beam","value-provider","runtime-context"],"backgroundTag":"invalid-state-transition","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}