flowable/flowable-engine · error · org.flowable.common.engine.api.FlowableException

unsupported operation on configuration beans

Error message

unsupported operation on configuration beans

What it means

SpringBeanFactoryProxyMap is a read-only Map facade over a Spring BeanFactory that resolves beans lazily via get(Object). Only lookups (get, containsKey) are supported; keySet() intentionally throws because bean names cannot be exposed as modifiable Map keys. This is a deliberate guard, not a bug.

Source

Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/cfg/SpringBeanFactoryProxyMap.java:52

    @Override
    public Object get(Object key) {
        if ((key == null) || !String.class.isAssignableFrom(key.getClass())) {
            return null;
        }
        return beanFactory.getBean((String) key);
    }

    @Override
    public boolean containsKey(Object key) {
        if ((key == null) || !String.class.isAssignableFrom(key.getClass())) {
            return false;
        }
        return beanFactory.containsBean((String) key);
    }

    @Override
    public Set<Object> keySet() {
        throw new FlowableException("unsupported operation on configuration beans");
        // List<String> beanNames =
        // Arrays.asList(beanFactory.getBeanDefinitionNames());
        // return new HashSet<Object>(beanNames);
    }

    @Override
    public void clear() {
        throw new FlowableException("can't clear configuration beans");
    }

    @Override
    public boolean containsValue(Object value) {
        throw new FlowableException("can't search values in configuration beans");
    }

    @Override
    public Set<Map.Entry<Object, Object>> entrySet() {
        throw new FlowableException("unsupported operation on configuration beans");

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Do not iterate the map; look up beans directly with map.get(beanName) or beanFactory.getBean(beanName)
  2. Use beanFactory.getBeanDefinitionNames() on the underlying ListableBeanFactory to enumerate bean names instead
  3. Copy only resolved entries: iterate your known bean names and call get() on each, building your own Map
  4. If you need a full Map, replace SpringBeanFactoryProxyMap with a concrete map populated from getBeanDefinitionNames()

Example fix

// before
for (Object beanName : springBeanFactoryProxyMap.keySet()) { ... }
// after
for (String beanName : listableBeanFactory.getBeanDefinitionNames()) {
    Object bean = springBeanFactoryProxyMap.get(beanName);
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (map instanceof SpringBeanFactoryProxyMap) {
    // use beanFactory.getBeanDefinitionNames() instead of keySet()
}

Type guard

boolean isReadOnlyBeanMap(Map<?,?> m) { return m instanceof SpringBeanFactoryProxyMap; }

Try / catch

try {
    keys = map.keySet();
} catch (FlowableException e) {
    if (e.getMessage() != null && e.getMessage().contains("unsupported operation")) {
        keys = new HashSet<>(Arrays.asList(listableBeanFactory.getBeanDefinitionNames()));
    } else { throw e; }
}

Prevention

When it happens

Trigger: Any code path that calls keySet() on a SpringBeanFactoryProxyMap instance, e.g. iterating map keys, copying the map into another Map via a constructor that reads keySet/entrySet, or framework code that introspects the Map.

Common situations: Passing the proxy map to utilities that copy or serialize Maps (new HashMap<>(map), MapUtils, Jackson/JSON serialization), debugging code that dumps map contents, or custom code iterating beans to find a candidate bean.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/6e3453425c9fd0c2. Report an issue: GitHub.