Skip to content
Back

Listing all function deployments from a function always causes an error

  • 0
  • Cloud
maru
22 Aug, 2025, 00:27

I have a function with the following code. Its purpose is to delete old deployments and win back storage capacity (since there's no option in the Console that I know of... please point me towards it if there is one <3)

TypeScript
import {serverFunctions} from '#/functions/appwriteClient.ts';
import type {IFunctionContext} from '#/functions/models.ts';
import {Query} from 'node-appwrite';

export default async ({res}: IFunctionContext) => {
    const functions = await serverFunctions.list();
    const deletionPromises: Promise<object>[] = [];

    console.log(`Found ${functions.total} functions. Deleting old deployments...`);

    for (const function_ of functions.functions) {
        const deploymentList = await serverFunctions.listDeployments(function_.$id, [Query.equal('activate', false)]);
        const deletableDeployments = deploymentList.deployments
            .map((deployment) => ({...deployment, $createdAt: new Date(deployment.$createdAt)}))
            .sort((a, b) => {
                const aSuccessful = a.status !== 'failed' ? 1 : 0;
                const bSuccessful = b.status !== 'failed' ? 1 : 0;

                if (!aSuccessful || !bSuccessful) {
                    return bSuccessful - aSuccessful;
                }

                return b.$createdAt.getTime() - a.$createdAt.getTime();
            });

        for (const deployment of deletableDeployments.slice(3)) {
            console.log(`Deleting deployment ${deployment.$id} for function ${function_.$id}`);
            deletionPromises.push(serverFunctions.deleteDeployment(function_.$id, deployment.$id));
        }
    }

    await Promise.all(deletionPromises);

    return res.empty();
};
TL;DR
Developers are encountering an error when listing all function deployments due to a scoped issue in the code. They are troubleshooting the use of header keys and API keys, as well as the endpoint for the FRA region. The shared code snippet seems fine, and the concern lies in whether it's a bug or an error on their end. Unfortunately, no clear solution is provided in the thread.
maru
22 Aug, 2025, 00:27

However, when I try to execute the function, I always get this error:

TypeScript
AppwriteException: app.xxx@service.cloud.appwrite.io (role: applications) missing scope (functions.read)
    at new AppwriteException (/usr/local/server/src/function/functions/node_modules/node-appwrite/dist/client.mjs:8:5)
    at <anonymous> (/usr/local/server/src/function/functions/node_modules/node-appwrite/dist/client.mjs:294:17)
    at processTicksAndRejections (:12:39)

The thing is... the function has that scope. In fact, I gave it all scopes just to test if something's missing...

maru
22 Aug, 2025, 00:47

It seems to already fail at serverFunctions.list() , since there are no other logs

maru
25 Aug, 2025, 13:12

can anyone help me? Is this a bug, or error on my side?

Steven
25 Aug, 2025, 18:55

what region is the project in?

maru
25 Aug, 2025, 19:14

it's in FRA

Steven
25 Aug, 2025, 21:03

hmm very odd...

Steven
25 Aug, 2025, 21:04

can you log the api key and DM it to me?

Steven
25 Aug, 2025, 21:04

it's dynamic, right?

maru
10 Sep, 2025, 20:13

so, unfortunately, after sending the key and everything, I never heard back from @Steven . Can anyone help me or will I need email support?

Steven
10 Sep, 2025, 20:29

sorry i lost track of the issue. so the key has these scopes:

TypeScript
    "sessions.write",
    "users.read",
    "users.write",
    "teams.read",
    "teams.write",
    "databases.read",
    "databases.write",
    "collections.read",
    "collections.write",
    "attributes.read",
    "attributes.write",
    "indexes.read",
    "indexes.write",
    "documents.read",
    "documents.write",
    "files.read",
    "files.write",
    "buckets.read",
    "buckets.write",
    "functions.read",
    "functions.write",
    "execution.read",
    "execution.write",
    "targets.read",
    "targets.write",
    "providers.read",
    "providers.write",
    "messages.read",
    "messages.write",
    "topics.read",
    "topics.write",
    "subscribers.read",
    "subscribers.write",
    "locale.read",
    "avatars.read",
    "health.read",
    "migrations.read",
    "migrations.write",
    "tokens.read",
    "tokens.write",
    "sites.read",
    "sites.write",
    "log.read",
    "log.write"
Steven
10 Sep, 2025, 20:30

which looks fine..

Steven
10 Sep, 2025, 20:33

can you share your code in '#/functions/appwriteClient.ts'?

maru
10 Sep, 2025, 20:46

Thank you for taking a look at it ❤️

#/functions/appwriteClient.ts is used by all my functions, and they all work great, however, here's the code for reference:

TypeScript
import { Account, Client, Databases, Functions, Storage, TablesDB, Teams, Users } from 'node-appwrite';

export const serverClient = new Client()
    .setEndpoint('https://cloud.appwrite.io/v1')
    // @ts-expect-error
    .setProject(Bun.env.APPWRITE_FUNCTION_PROJECT_ID)
    // @ts-expect-error
    .setKey(Bun.env.APPWRITE_API_KEY);

// assign session before use
export const sessionClient = new Client()
    .setEndpoint('https://cloud.appwrite.io/v1')
    // @ts-expect-error
    .setProject(Bun.env.APPWRITE_FUNCTION_PROJECT_ID);

export const serverAccount = new Account(serverClient);
export const serverDatabases = new Databases(serverClient);
export const serverFunctions = new Functions(serverClient);
export const serverStorage = new Storage(serverClient);
export const serverTables = new TablesDB(serverClient);
export const serverTeams = new Teams(serverClient);
export const serverUsers = new Users(serverClient);

export const sessionAccount = new Account(sessionClient);
export const sessionStorage = new Storage(sessionClient);
James
10 Sep, 2025, 20:56

If it's FRA region, does the endpoint need to be https://fra.cloud.appwrite.io/v1 instead of https://cloud.appwrite.io/v1

James
10 Sep, 2025, 20:58

if I'm not mistaken, you could use

TypeScript
 .setEndpoint(Bun.env.APPWRITE_FUNCTION_API_ENDPOINT)
Steven
10 Sep, 2025, 21:24

Wait it's using an API key, not the dynamic key 🧐

maru
16 Sep, 2025, 07:16

oh, you're right! Just to check: In order to use the dynamic key, all I have to do is use the header x-appwrite-key instead, right?

maru
16 Sep, 2025, 07:19

Do you have a best practice for providing the client globally (e.g. can I update the client from a different place when I handle the request) or is it better to use a state object which I pass around (I already have that, it's just not providing the client right now)?

Steven
16 Sep, 2025, 19:57

Yes, correct

Steven
16 Sep, 2025, 20:00

You should definitely scope it to the current request

Reply

Reply to this thread by joining our Discord

Reply on Discord

Need support?

Join our Discord

Get community support by joining our Discord server.

Join Discord

Get premium support

Join Appwrite Pro and get email support from our team.

Learn more