appwrite/appwrite · error · Exception

Failed to issue a certificate with message: {stderr}

Error message

Failed to issue a certificate with message: {stderr}

What it means

DELETE /v1/functions/{functionId}/variables/{variableId} loads the parent function first; if getDocument('functions', $functionId) is empty it throws function_not_found (src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php:81) before the variable is even looked up.

Source

Thrown at src/Appwrite/Certificates/LetsEncrypt.php:41

    {
        $stdout = '';
        $stderr = '';

        $staging = (Http::isProduction()) ? '' : ' --dry-run';
        $exit = Console::execute(
            "certbot certonly -v --webroot --noninteractive --agree-tos{$staging}"
            . " --email " . $this->email
            . " --cert-name " . $certName
            . " -w " . APP_STORAGE_CERTIFICATES
            . " -d {$domain}",
            '',
            $stdout,
            $stderr
        );

        // Unexpected error, usually 5XX, API limits, ...
        if ($exit !== 0) {
            throw new Exception('Failed to issue a certificate with message: ' . $stderr);
        }

        // Prepare folder in storage for domain
        $path = APP_STORAGE_CERTIFICATES . '/' . $domain;
        if (!\is_readable($path)) {
            if (!\mkdir($path, 0755, true)) {
                throw new Exception('Failed to create path for certificate.');
            }
        }

        // Move generated files
        if (!@\rename('/etc/letsencrypt/live/' . $certName . '/cert.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/cert.pem')) {
            throw new Exception('Failed to rename certificate cert.pem. Let\'s Encrypt log: ' . $stderr . ' ; ' . $stdout);
        }

        if (!@\rename('/etc/letsencrypt/live/' . $certName . '/chain.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/chain.pem')) {
            throw new Exception('Failed to rename certificate chain.pem. Let\'s Encrypt log: ' . $stderr . ' ; ' . $stdout);
        }

View on GitHub (pinned to a1d520eea4)

Solutions

  1. Resolve the function id via GET /v1/functions (list) before deleting its variables
  2. Treat function_not_found on delete as already-done when writing idempotent cleanup
  3. Verify the SDK/API-key project context matches the function's project

Example fix

// before
await functions.variables.delete('fnct_old_id', varId);

// after
const fns = await functions.list();
const fn = fns.functions.find((f) => f.name === 'payments');
if (fn) await functions.variables.delete(fn.$id, varId);
Defensive patterns

Strategy: validation

Validate before calling

const fns = (await functions.list()).functions.map((f) => f.$id);
if (!fns.includes(fnId)) {
  console.warn(`function ${fnId} no longer exists; skipping variable cleanup`);
}

Try / catch

try {
  await functions.variables.delete(fnId, varId);
} catch (e) {
  if (e instanceof AppwriteException && e.code === 'function_not_found') {
    // parent already gone: nothing to clean, treat as success
  } else throw e;
}

Prevention

When it happens

Trigger: Deleting a variable with a mistyped functionId; deleting against a function that was removed; using credentials bound to a different project.

Common situations: Cleanup scripts run after functions were re-created with new ids; environments drifted so the script's functionId list no longer matches the project.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of appwrite/appwrite@a1d520eea4 (2026-08-18). Data as JSON: /api/errors/db37fb5c24f0cde3. Report an issue: GitHub.