flowable/flowable-engine · error · UsernameNotFoundException

user ( ) could not be found

Error message

user (%s) could not be found

What it means

Flowable's Spring Security integration implements UserDetailsService on top of the Flowable identity (IDM) tables. loadUserByUsername looks up the user via the IdmIdentityService; if no row matches the given userId (after swallowing the FlowableException from the query), it throws Spring Security's UsernameNotFoundException. It signals that authentication cannot proceed because the account does not exist in the Flowable IDM database.

Solutions

  1. Insert the user into the IDM schema (ACT_ID_USER) via the IdmIdentityService (idmIdentityService.createUser(...).setPassword(...)) or the Flowable Admin/IDM UI, then retry login.
  2. If users live in LDAP/AD, configure Flowable's LDAP identity integration or a different UserDetailsService instead of relying on the IDM tables.
  3. Verify the application is connected to the intended database (check flowable/database config) — the user may exist in another environment's DB.
  4. Catch UsernameNotFoundException in your authentication handling and show a clear 'unknown user' message instead of a generic failure.

Example fix

// before (user missing at login)
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("jsmith", "secret"));
// throws UsernameNotFoundException: user (jsmith) could not be found

// after: provision the user first if missing
if (idmIdentityService.createUserQuery().userId("jsmith").singleResult() == null) {
    User u = idmIdentityService.newUser("jsmith");
    u.setPassword(passwordEncoder.encode("secret"));
    u.setFirstName("John");
    u.setLastName("Smith");
    idmIdentityService.saveUser(u);
}
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("jsmith", "secret"));
Defensive patterns

Strategy: try-catch

Validate before calling

boolean exists = idmIdentityService.createUserQuery().userId(userId).singleResult() != null;

Try / catch

try {
    UserDetails user = userDetailsService.loadUserByUsername(userId);
} catch (UsernameNotFoundException e) {
    // provision or reject with 'unknown user' response; never reveal stack trace to clients
}

Prevention

When it happens

Trigger: Calling FlowableUserDetailsService.loadUserByUsername(userId) when the ACT_ID_USER table has no row with that ID; also triggered indirectly by any Spring Security authentication (form login, DaoAuthenticationProvider) configured with this UserDetailsService for a username that is not a Flowable IDM user.

Common situations: Users provisioned in an external directory (LDAP/AD) but the Flowable IDM tables were never synced; typos or case-sensitivity mismatches in usernames; pointing the app at a fresh database without running the identity data scripts; deleting a user while active sessions still reference them.

Understand the failure class

Background: "User not found", "Invalid user", and "does not exist": what missing-user lookup errors mean across Rocket.Chat, LiteLLM, Phabricator, rustfs, and pnpm — this error's family across 10 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-spring-security/src/main/java/org/flowable/spring/security/FlowableUserDetailsService.java:59

    public FlowableUserDetailsService(IdmIdentityService identityService) {
        this.identityService = identityService;
    }

    @Override
    public UserDetails loadUserByUsername(String userId)
            throws UsernameNotFoundException {
        User user = null;
        try {
            user = this.identityService.createUserQuery()
                    .userId(userId)
                    .singleResult();
        } catch (FlowableException ex) {
            // don't care
        }

        if (null == user) {
            throw new UsernameNotFoundException(
                    String.format("user (%s) could not be found", userId));
        }

        return createFlowableUser(user);
    }

    protected FlowableUser createFlowableUser(User user) {

        String userId = user.getId();
        List<Privilege> userPrivileges = identityService.createPrivilegeQuery().userId(userId).list();
        Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
        for (Privilege userPrivilege : userPrivileges) {
            grantedAuthorities.add(new SimpleGrantedAuthority(userPrivilege.getName()));
        }

        List<Group> groups = identityService.createGroupQuery().groupMember(userId).list();
        if (!groups.isEmpty()) {
            List<String> groupIds = new ArrayList<>(groups.size());

View on GitHub (pinned to d6d39ce1c6)