apereo/cas · warning

e.getMessage() (ResourceNotFoundException logged during…

Error message

e.getMessage() (ResourceNotFoundException logged during deleteAll)

What it means

DynamoDbTicketRegistryFacilitator.deleteAll() runs a batch deletion of all tickets via a deletor callable. If DynamoDB throws ResourceNotFoundException (the ticket table does not exist), the code logs the exception message at WARN, recreates the missing ticket tables via createTicketTables(false), and retries the deletion once. The error item here is the WARN log line — an application-level recovery, not a thrown exception to callers.

Solutions

  1. Let the built-in recovery work: the registry recreates tables and retries; confirm logs show 'createTicketTables' succeeding afterwards
  2. Verify cas.ticket.registry.dynamo-db settings (region, endpoint, table prefix) match the actual DynamoDB environment
  3. Check AWS IAM permissions for CreateTable/DeleteItem on the configured tables
  4. If tables were deleted intentionally, restart CAS or trigger table creation so state is consistent
  5. For local dev, start the DynamoDB test container (ci tests) before running registry operations

Example fix

// before: region mismatch — table exists in us-east-1, CAS looks in eu-west-1
# cas.ticket.registry.dynamo-db.region=eu-west-1
// after
cas.ticket.registry.dynamo-db.region=us-east-1
Defensive patterns

Strategy: retry

Validate before calling

// Before deleteAll, confirm the table exists:
DescribeTableRequest req = DescribeTableRequest.builder()
    .tableName(tableName).build();
dynamoDbClient.describeTable(req); // throws ResourceNotFoundException if missing

Try / catch

try {
    return deletor.get();
} catch (ResourceNotFoundException e) {
    LOGGER.warn(e.getMessage(), e);
    createTicketTables(false);   // recreate, then retry once
    return deletor.get();
}

Prevention

When it happens

Trigger: Calling deleteAll() (e.g. purge-all tickets operation or scheduled cleanup) when the DynamoDB table backing the ticket registry does not exist: fresh environment before table auto-creation, tables deleted manually in AWS console, wrong region/profile/table-prefix configuration pointing to a nonexistent table, or IAM/region mismatch.

Common situations: Deploying CAS against a new DynamoDB account/region without letting CAS create its tables; someone dropped the CAS ticket tables; cas.ticket.registry.dynamo-db table-prefix mismatch between nodes; using a DynamoDB endpoint (local test container) that was wiped between runs.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at support/cas-server-support-dynamodb-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/DynamoDbTicketRegistryFacilitator.java:164

     * @return the int
     */
    public int deleteAll() {
        val deletor = new Supplier<Integer>() {
            @Override
            public Integer get() {
                val count = new AtomicInteger();
                val metadata = ticketCatalog.findAll();
                metadata.forEach(definition -> {
                    val tableName = definition.getProperties().getStorageName();
                    count.addAndGet(Math.toIntExact(deleteTickets(tableName, scanTicketIds(tableName))));
                });
                return count.get();
            }
        };
        try {
            return deletor.get();
        } catch (final ResourceNotFoundException e) {
            LOGGER.warn(e.getMessage(), e);
            createTicketTables(false);
            return deletor.get();
        }
    }

    /**
     * Scan and paginate.
     *
     * @return the stream
     */
    public Stream<Ticket> stream() {
        val metadata = ticketCatalog.findAll();
        val resultStreams = metadata
            .stream()
            .map(defn -> queryTicketsByIndex(defn.getProperties().getStorageName(),
                PREFIX_INDEX_NAME, ColumnNames.PREFIX, defn.getPrefix(), 0, true))
            .toList();
        return Streams.concat(resultStreams.toArray(new Stream[0]));

View on GitHub (pinned to e7288fc434)