xai-org/x-algorithm · critical · FileNotFoundError

Keytab file not found

Error message

Keytab file not found: {self.config.keytab_path}

What it means

KerberosClient.__init__ validates that the keytab file exists on disk before attempting any kinit. If Path(keytab_path) does not exist it raises FileNotFoundError with the configured path, so misconfigured paths fail at construction rather than deep inside the renewal loop.

Solutions

  1. Verify the path exists in the runtime: kubectl exec -- ls -l <path> or ls locally.
  2. Mount the keytab Secret at the configured path (volumes/volumeMounts) or point keytab_path at the real location.
  3. If templated, ensure env expansion happens before constructing the client.

Example fix

# before
client = KerberosClient('/etc/secrets/krb5.keytab', 'svc@REALM')  # FileNotFoundError

# after
# mount the secret at /etc/secrets, then
client = KerberosClient('/etc/secrets/krb5.keytab', 'svc@REALM')
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path
if not Path(keytab_path).is_file():
    raise SystemExit(f'keytab missing: {keytab_path}')
client = KerberosClient(keytab_path, principal)

Try / catch

try:
    client = KerberosClient(kt, principal)
except FileNotFoundError as e:
    logger.error('keytab not mounted: %s', e)
    raise

Prevention

When it happens

Trigger: new KerberosClient(keytab_path='/etc/krb5/missing.keytab', ...) where the file is absent; also a relative path resolved against an unexpected working directory, or a secret not mounted in the container.

Common situations: k8s Secret not mounted / mounted at a different path; running locally where /etc/... does not exist; path from config with a typo or with $VAR placeholders unexpanded; container running as a user without read access making exists() effectively unusable later.

Related errors


AI-assisted analysis of xai-org/x-algorithm@24c60942c5 (2026-08-28). Data as JSON: /api/errors/2e7f5b86d378e641. Report an issue: GitHub.

Appendix: source

Thrown at grox/libs/kerberos_cli/kerberos.py:26

logger = logging.getLogger(__name__)


class KerberosConfig(BaseModel):
    keytab_path: str
    principal: str
    renew_interval: int = 3600
    attempts: int = 5
    retry_interval: int = 60


class KerberosRenewer:
    def __init__(self, keytab_path: str, principal: str, **kwargs):
        self._renewer: asyncio.Task | None = None
        self.config = KerberosConfig(
            keytab_path=keytab_path, principal=principal, **kwargs
        )
        if not Path(self.config.keytab_path).exists():
            raise FileNotFoundError(f"Keytab file not found: {self.config.keytab_path}")
        if self.config.renew_interval <= 0:
            raise ValueError("Renew interval must be greater than 0")
        if self.config.attempts <= 0:
            raise ValueError("Attempts must be greater than 0")
        if self.config.retry_interval <= 0:
            raise ValueError("Retry interval must be greater than 0")

    async def _kerberos_renewal_loop(self):
        while True:
            attempts = self.config.attempts
            while attempts > 0:
                attempts -= 1
                try:
                    await self._renew_kerberos_ticket()
                    logger.info(
                        f"Kerberos ticket renewed successfully for {self.config.principal}"
                    )
                    break

View on GitHub (pinned to 24c60942c5)