apache/flink · error · IllegalStateException

Queryable state name already set

Error message

Queryable state name already set

What it means

setQueryable attempts to register a queryable-state name on the descriptor, but queryableStateName is already non-null from a previous successful call. A descriptor can only carry one queryable name. The method also guards against TTL being enabled (Queryable state is not supported with TTL) before reaching this check.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/common/state/StateDescriptor.java:245

     * <p>If a name is set, the created state will be published for queries during runtime. The name
     * needs to be unique per job. If there is another state instance published under the same name,
     * the job will fail during runtime.
     *
     * @param queryableStateName State name for queries (unique name per job)
     * @throws IllegalStateException If queryable state name already set
     * @deprecated The Queryable State feature is deprecated since Flink 1.18, and will be removed
     *     in a future Flink major version.
     */
    @Deprecated
    public void setQueryable(String queryableStateName) {
        Preconditions.checkArgument(
                ttlConfig.getUpdateType() == StateTtlConfig.UpdateType.Disabled,
                "Queryable state is currently not supported with TTL");
        if (this.queryableStateName == null) {
            this.queryableStateName =
                    Preconditions.checkNotNull(queryableStateName, "Registration name");
        } else {
            throw new IllegalStateException("Queryable state name already set");
        }
    }

    /**
     * Returns the queryable state name.
     *
     * @return Queryable state name or <code>null</code> if not set.
     * @deprecated The Queryable State feature is deprecated since Flink 1.18, and will be removed
     *     in a future Flink major version.
     */
    @Nullable
    @Deprecated
    public String getQueryableStateName() {
        return queryableStateName;
    }

    /**
     * Returns whether the state created from this descriptor is queryable.

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Guard the call with descriptor.isQueryable() (or check getQueryableStateName() == null) before invoking setQueryable.
  2. Ensure setQueryable is called exactly once per descriptor lifecycle; remove duplicate calls.
  3. Note the feature is deprecated since Flink 1.18 and scheduled for removal — prefer another state-query mechanism and drop setQueryable entirely.

Example fix

// before
desc.setQueryable("myState");
...
desc.setQueryable("myState"); // throws on second call

// after
if (!desc.isQueryable()) {
    desc.setQueryable("myState");
}
Defensive patterns

Strategy: validation

Validate before calling

if (!descriptor.isQueryable()) {
    descriptor.setQueryable(queryableStateName);
} else if (!descriptor.getQueryableStateName().equals(queryableStateName)) {
    throw new IllegalStateException(
        "Descriptor already registered as queryable: "
            + descriptor.getQueryableStateName());
}

Type guard

// Guard against duplicate registration
if (descriptor.isQueryable()) {
    // already set; skip or assert the same name
}

Try / catch

try {
    descriptor.setQueryable(name);
} catch (IllegalStateException e) {
    // already registered; ignore if same name, else surface
    if (!name.equals(descriptor.getQueryableStateName())) throw e;
}

Prevention

When it happens

Trigger: Calling setQueryable("name") twice on the same StateDescriptor instance; framework or helper code that registers queryable state and the user also calls it manually; copy-paste duplication of the setQueryable line.

Common situations: Reusable descriptor objects passed to multiple operators where each calls setQueryable; refactoring that leaves a stray setQueryable call alongside a new one; the queryable state feature being deprecated (since 1.18) so users migrating away hit this while toggling settings.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/5f2695c073defdc2. Report an issue: GitHub.