{"record":{"id":"88dd87ab73062167","repo":"apereo/cas","slug":"unable-to-pull-changes-from-the-remote-repository","errorCode":null,"errorMessage":"Unable to pull changes from the remote repository. Metadata files may be stale.","messagePattern":"Unable to pull changes from the remote repository\\. Metadata files may be stale\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"support/cas-server-support-saml-idp-metadata-git/src/main/java/org/apereo/cas/support/saml/idp/metadata/GitSamlIdPMetadataLocator.java","lineNumber":41,"sourceCode":" */\n@Slf4j\npublic class GitSamlIdPMetadataLocator extends FileSystemSamlIdPMetadataLocator {\n    private final GitRepository gitRepository;\n\n    public GitSamlIdPMetadataLocator(final GitRepository gitRepository,\n                                     final Cache<String, SamlIdPMetadataDocument> metadataCache,\n                                     final CipherExecutor cipherExecutor,\n                                     final ConfigurableApplicationContext applicationContext) {\n        super(cipherExecutor, gitRepository.getRepositoryDirectory(), metadataCache, applicationContext);\n        this.gitRepository = gitRepository;\n    }\n\n    @Override\n    public SamlIdPMetadataDocument fetchInternal(final Optional<SamlRegisteredService> registeredService) throws Exception {\n        if (gitRepository.pull()) {\n            LOGGER.debug(\"Successfully pulled metadata changes from the remote repository\");\n        } else {\n            LOGGER.warn(\"Unable to pull changes from the remote repository. Metadata files may be stale.\");\n        }\n\n        val metadataFile = getMetadataArtifactFile(registeredService, \"idp-metadata.xml\");\n        LOGGER.trace(\"IdP metadata file to use is [{}]\", metadataFile);\n\n        val signingKey = getMetadataArtifactFile(registeredService, \"idp-signing.key\");\n        LOGGER.trace(\"IdP metadata signing key file to use is [{}]\", metadataFile);\n\n        val signingCert = getMetadataArtifactFile(registeredService, \"idp-signing.crt\");\n        LOGGER.trace(\"IdP metadata signing certificate file to use is [{}]\", metadataFile);\n\n        val encryptionKey = getMetadataArtifactFile(registeredService, \"idp-encryption.key\");\n        LOGGER.trace(\"IdP metadata encryption key file to use is [{}]\", metadataFile);\n\n        val encryptionCert = getMetadataArtifactFile(registeredService, \"idp-encryption.crt\");\n        LOGGER.trace(\"IdP metadata encryption certificate file to use is [{}]\", metadataFile);\n\n        return SamlIdPMetadataDocument.builder()","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-saml-idp-metadata-git/src/main/java/org/apereo/cas/support/saml/idp/metadata/GitSamlIdPMetadataLocator.java#L23-L59","documentation":"This is a WARN log, not a thrown exception, emitted by GitSamlIdPMetadataLocator.fetchInternal when gitRepository.pull() returns false during an attempt to update the local clone of the IdP metadata Git repository. The locator continues serving metadata from the last successfully pulled working copy, so the message warns that the local files may be stale relative to the remote. CAS logs it rather than failing because serving stale metadata is usually preferable to serving none.","triggerScenarios":"Any call to fetchInternal where the underlying Git repository pull fails: no remote configured, remote unreachable (network/DNS/proxy), authentication failure to the remote, non-git or corrupted local clone directory, merge conflicts or detached HEAD in the clone, or JGit pull returning false because the working tree is dirty.","commonSituations":"Deployment moved behind a firewall blocking the metadata Git remote; SSH key or token for the remote expired; the metadata repo directory was manually modified so the pull aborts; cas.authn.saml.idp.metadata.git.* remote-url misconfigured after migrating repos.","solutions":["Verify network connectivity and the remote URL configured for the Git metadata repository (git fetch manually in the configured clone directory).","Check remote credentials (SSH key passphrase, deploy token) and that the CAS process user can read/write the clone directory.","Inspect the clone for dirty working tree, merge conflicts, or detached HEAD; reset/clean it and retry startup.","Enable DEBUG logging for the Git locator and JGit to see the underlying pull failure cause.","If offline operation is intended, accept the warning or remove the git-backed locator in favor of a local filesystem locator."],"exampleFix":"// before: relying on default remote without credentials\ncas.authn.saml.idp.metadata.git.remote-url=git@internal-git:cas/metadata.git\n// after: ensure reachable HTTPS remote and credentials are provisioned\ncas.authn.saml.idp.metadata.git.remote-url=https://internal-git/cas/metadata.git\ncas.authn.saml.idp.metadata.git.username=cas-bot\ncas.authn.saml.idp.metadata.git.token=***","handlingStrategy":"validation","validationCode":"// Before enabling the git-backed locator, probe the repo\nvar cmd = new ProcessBuilder(\"git\", \"-C\", metadataDir, \"fetch\", \"--dry-run\");\nif (cmd.start().waitFor() != 0) {\n    throw new IllegalStateException(\"Git metadata repo unreachable or misconfigured: \" + metadataDir);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Smoke-test git pull in the configured clone directory after any network or credential change","Run the CAS process as a user with read/write access to the clone and SSH/HTTPS credentials","Monitor logs for this WARN and alert, since stale metadata degrades silently","Keep the clone clean: never edit files inside it manually"],"tags":["git","saml-metadata","network","stale-data"],"backgroundTag":"git-command-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"}