apereo/cas · warning

JSON account repository file

Error message

JSON account repository file [{}] is not found.

What it means

JsonGoogleAuthenticatorTokenCredentialRepository.get() reads accounts from a JSON file backed by a Spring Resource. If the file does not exist at the configured location it logs this warning and returns an empty list instead of failing, so lookups silently find no account.

Solutions

  1. Create the JSON account file at the configured location (can start as an empty JSON array) or ensure the path is writable so save() can create it
  2. Verify the cas.authn.mfa.gauth.core.json-file/resource path is correct and reachable from the CAS process
  3. If provisioning externally, mount or copy the pre-populated accounts file before startup
  4. Confirm the resource is resolvable as a file (file: URLs must point to the actual filesystem, not inside an unreadable jar)

Example fix

// before
cas.authn.mfa.gauth.core.json-file=/etc/cas/config/gauth-accnts.json
// after (typo fixed and file pre-created with [])
touch /etc/cas/config/gauth-accounts.json && echo '[]' > /etc/cas/config/gauth-accounts.json
cas.authn.mfa.gauth.core.json-file=file:/etc/cas/config/gauth-accounts.json
Defensive patterns

Strategy: fallback

Validate before calling

// pre-check the configured store before login flows run
Resource loc = ...;
boolean storeReady = loc != null && loc.getFile().exists() && loc.getFile().length() > 0;

Try / catch

try {
    accounts = repository.get(username);
} catch (Exception e) {
    accounts = List.of(); // empty fallback; treat as 'no devices registered'
}

Prevention

When it happens

Trigger: Calling get(username) when the configured ResourceLocation (e.g. cas.authn.mfa.gauth.core.json-file or a repository resource) points to a path that has not been created yet, typically on first startup before any account registration.

Common situations: Fresh deployment where the JSON store file was never initialized; wrong absolute path or missing mount in a container; file deleted by cleanup jobs; file expected on a classpath location that isn't packaged.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/6fbd892b0a07156b. Report an issue: GitHub.

Appendix: source

Thrown at support/cas-server-support-gauth-core/src/main/java/org/apereo/cas/gauth/credential/JsonGoogleAuthenticatorTokenCredentialRepository.java:71

        });
    }

    @Override
    public OneTimeTokenAccount get(final String username, final long id) {
        return lock.tryLock(() -> get(username)
            .stream()
            .filter(ac -> ac.getId() == id)
            .findFirst()
            .map(this::decode)
            .orElse(null));
    }

    @Override
    public Collection<? extends OneTimeTokenAccount> get(final String username) {
        return lock.tryLock(() -> {
            try {
                if (!location.getFile().exists()) {
                    LOGGER.warn("JSON account repository file [{}] is not found.", location.getFile());
                    return new ArrayList<>();
                }

                if (location.getFile().length() <= 0) {
                    LOGGER.debug("JSON account repository file location [{}] is empty.", location.getFile());
                    return new ArrayList<>();
                }
                val map = serializer.from(location.getFile());
                if (map == null) {
                    LOGGER.debug("JSON account repository file [{}] is empty.", location.getFile());
                    return new ArrayList<>();
                }

                val account = map.get(username.trim().toLowerCase(Locale.ENGLISH));
                if (account != null) {
                    return decode(account);
                }
            } catch (final Exception e) {

View on GitHub (pinned to e7288fc434)