xai-org/x-algorithm · critical · FileNotFoundError

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

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.

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)

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.