spring-projects/spring-security · error · NotFoundException

Object identity not found: <objectIdentity>

Error message

Object identity not found: <objectIdentity>

What it means

deleteAcl resolves the target object identity's primary key in acl_object_identity before deleting its entries and row. If retrieveObjectIdentityPrimaryKey returns null — no ACL row exists for that ObjectIdentity — the service throws NotFoundException because there is nothing to delete.

Source

Thrown at acl/src/main/java/org/springframework/security/acls/jdbc/JdbcMutableAclService.java:300

					deleteAcl(child, true);
				}
			}
		}
		else {
			if (!this.foreignKeysInDatabase) {
				// We need to perform a manual verification for what a FK would normally
				// do. We generally don't do this, in the interests of deadlock management
				List<ObjectIdentity> children = findChildren(objectIdentity);
				if (children != null) {
					throw new ChildrenExistException(
							"Cannot delete '" + objectIdentity + "' (has " + children.size() + " children)");
				}
			}
		}

		Long oidPrimaryKey = retrieveObjectIdentityPrimaryKey(objectIdentity);
		if (oidPrimaryKey == null) {
			throw new NotFoundException("Object identity not found: " + objectIdentity);
		}

		// Delete this ACL's ACEs in the acl_entry table
		deleteEntries(oidPrimaryKey);

		// Delete this ACL's acl_object_identity row
		deleteObjectIdentity(oidPrimaryKey);

		// Clear the cache
		this.aclCache.evictFromCache(objectIdentity);
	}

	/**
	 * Deletes all ACEs defined in the acl_entry table belonging to the presented
	 * ObjectIdentity primary key.
	 * @param oidPrimaryKey the rows in acl_entry to delete
	 */
	protected void deleteEntries(Long oidPrimaryKey) {

View on GitHub (pinned to 96852e8860)

Solutions

  1. Check existence first (retrieveObjectIdentityPrimaryKey or readAclById) and skip deleteAcl when absent.
  2. Catch org.springframework.security.acls.model.NotFoundException and treat delete as a no-op (idempotent delete).
  3. Verify the ObjectIdentity type/identifier matches acl_class/acl_object_identity exactly.
  4. Confirm the delete is running against the correct datasource/schema.

Example fix

// before
mutableAclService.deleteAcl(oid, true);
// after
try {
    mutableAclService.deleteAcl(oid, true);
} catch (NotFoundException ex) {
    // ACL already gone; idempotent delete
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (((JdbcMutableAclService) aclService).retrieveObjectIdentityPrimaryKey(oid) == null) {
    return; // nothing to delete
}

Type guard

null

Try / catch

try {
    mutableAclService.deleteAcl(oid, true);
} catch (NotFoundException e) {
    // idempotent: ACL already gone
}

Prevention

When it happens

Trigger: Calling deleteAcl(objectIdentity, ...) for an ObjectIdentity that was never persisted via createAcl, or deleting twice (double-invocation of a cleanup path), or an identity whose type/identifier spelling differs from the persisted row.

Common situations: Synchronization jobs deleting ACLs for entities already purged; retrying a delete after a partial failure where the ACL row was already removed; deleting ACLs for test data in a fresh database; environment mismatch (ACLs live in another schema).

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/031b1b37f31e59ee. Report an issue: GitHub.