{"record":{"id":"424ae1e60ab41d5f","repo":"apereo/cas","slug":"failed-to-delete-service-definition-file","errorCode":null,"errorMessage":"Failed to delete service definition file [{}]","messagePattern":"Failed to delete service definition file \\[(.+?)\\]","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"core/cas-server-core-services-registry/src/main/java/org/apereo/cas/services/resource/AbstractResourceBasedServiceRegistry.java","lineNumber":218,"sourceCode":"            LOGGER.debug(\"Saved service to [{}]\", fileName.getCanonicalPath());\n        } catch (final IOException e) {\n            throw new IllegalArgumentException(\"IO error opening file stream.\", e);\n        }\n        return findServiceById(service.getId());\n    }\n\n    @Override\n    public boolean delete(final RegisteredService service) {\n        return lock.tryLock(() -> FunctionUtils.doUnchecked(() -> {\n            val filename = getRegisteredServiceFileName(service);\n            val clientInfo = ClientInfoHolder.getClientInfo();\n            publishEvent(new CasRegisteredServicePreDeleteEvent(this, service, clientInfo));\n            val result = !filename.exists() || filename.delete();\n            if (result) {\n                removeRegisteredService(service);\n                LOGGER.debug(\"Successfully deleted service definition file [{}]\", filename.getCanonicalPath());\n            } else {\n                LOGGER.warn(\"Failed to delete service definition file [{}]\", filename.getCanonicalPath());\n            }\n            publishEvent(new CasRegisteredServiceDeletedEvent(this, service, clientInfo));\n            return result;\n        }));\n    }\n\n    @Override\n    public void deleteAll() {\n        val files = FileUtils.listFiles(this.serviceRegistryDirectory.toFile(), getExtensions(), true);\n        files.forEach(File::delete);\n    }\n\n    @Override\n    public Collection<RegisteredService> load() {\n        return lock.tryLock(() -> {\n            LOGGER.trace(\"Loading files from [{}]\", this.serviceRegistryDirectory);\n            val serviceRegistryDirectoryFile = serviceRegistryDirectory.toFile();\n            val files = serviceRegistryDirectoryFile.exists()","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/core/cas-server-core-services-registry/src/main/java/org/apereo/cas/services/resource/AbstractResourceBasedServiceRegistry.java#L200-L236","documentation":"AbstractResourceBasedServiceRegistry.delete attempts to remove the on-disk file backing a registered service. If File.delete() fails (file missing write permission on the directory, locked by another process, or a race), CAS logs this warning and returns false, leaving the service definition file in place.","triggerScenarios":"Calling serviceRegistry.delete(service) (via ServicesManager or the management app) where filename.exists() but filename.delete() returns false; the publishEvent/removeRegisteredService path is skipped only for the warn log but result remains false.","commonSituations":"Services directory owned by a different user than the CAS process; read-only mounted volume; NFS/Windows file locks; file recreated by a watcher between existence check and delete.","solutions":["Check filesystem permissions on the services directory and file: the CAS process user needs write permission on both.","Verify the volume is not mounted read-only (docker mount flags, k8s readOnlyRootFilesystem).","Check for file locks or a process holding the file open, then retry the delete.","Manually remove the stale file and reload the registry."],"exampleFix":"// before: delete fails silently with warning\nchown -R cas:cas /etc/cas/config/services\n// after\nchmod -R u+rw /etc/cas/config/services  # run as the CAS process user","handlingStrategy":"retry","validationCode":"// Pre-check before delete\nFile f = new File(filePath);\nif (f.exists() && !f.canWrite()) throw new AccessDeniedException(filePath);\nFile dir = f.getParentFile();\nif (!dir.canWrite()) throw new AccessDeniedException(dir.getPath());","typeGuard":null,"tryCatchPattern":"// Treat false return as retryable\nboolean deleted = serviceRegistry.delete(service);\nif (!deleted) { /* check permissions/locks, retry with backoff or delete manually */ }","preventionTips":["Run the CAS process as the owner of the services directory.","Avoid read-only mounts for directories that must accept writes.","Don't hold service files open in editors/other processes during deletes."],"tags":["filesystem","file-delete","permissions"],"backgroundTag":"file-write-failed","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}