flowable/flowable-engine · error · ActivitiException

unsupported operation on configuration beans

Error message

unsupported operation on configuration beans

What it means

SpringBeanFactoryProxyMap is a read-only Map view over a Spring BeanFactory used by the legacy Activiti engine to resolve beans by name. Mutating or enumerating Map methods that the bean factory cannot meaningfully support are deliberately unimplemented and throw ActivitiException. keySet() is one of these unsupported methods.

Source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/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 ActivitiException("unsupported operation on configuration beans");
        // List<String> beanNames = Arrays.asList(beanFactory.getBeanDefinitionNames());
        // return new HashSet<Object>(beanNames);
    }

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

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

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

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Do not enumerate the map; look up beans directly with get(key) or containsKey(key)
  2. Use beanFactory.getBeanDefinitionNames() on the underlying ListableBeanFactory to list bean names instead
  3. Wrap only if you need iteration: build your own map from getBeanDefinitionNames() and getBean(name)
  4. Remove code paths (loggers/serializers) that treat this map as a full Map

Example fix

// before
for (Object key : springBeanFactoryProxyMap.keySet()) { ... }
// after
for (String name : ((ListableBeanFactory) beanFactory).getBeanDefinitionNames()) {
    Object bean = springBeanFactoryProxyMap.get(name);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (map instanceof SpringBeanFactoryProxyMap) {
    // do not enumerate keys; resolve names via ListableBeanFactory.getBeanDefinitionNames()
}

Type guard

boolean isReadOnlyBeanMap = (map instanceof SpringBeanFactoryProxyMap);

Try / catch

try {
    Set<Object> keys = map.keySet();
} catch (ActivitiException e) {
    // fall back to beanFactory.getBeanDefinitionNames()
}

Prevention

When it happens

Trigger: Calling keySet() on a SpringBeanFactoryProxyMap instance, e.g. iterating the map's keys, copying it into another Map, or framework code that enumerates map keys (logging, serialization, copy constructors).

Common situations: Debug code printing the whole map; passing the map to utilities like Collections.copy or Jackson serialization that call keySet(); trying to copy beans from the map during a migration.

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/afb3ec566a0ea4eb. Report an issue: GitHub.