Description
The client.aiGateway.logs.list() method accepts a typed filters parameter (Array<LogListParams.Filter>), but the filters are silently ignored by the API because stringifyQuery serializes them in a format the API doesn't understand.
Root cause
The Cloudflare SDK overrides stringifyQuery in src/index.ts:480:
protected override stringifyQuery(query: Record<string, unknown>): string {
return qs.stringify(query, { allowDots: true, arrayFormat: 'repeat' });
}
With arrayFormat: 'repeat' and allowDots: true, an array of filter objects like:
filters: [
{ key: "metadata.key", operator: "eq", value: ["requestId"] },
{ key: "metadata.value", operator: "eq", value: ["abc-123"] },
]
Gets serialized as:
filters.key=metadata.key&filters.operator=eq&filters.value=requestId&filters.key=metadata.value&filters.operator=eq&filters.value=abc-123
This flat serialization loses the array structure — the API can't determine which key belongs to which operator/value. The result is the API ignoring the filters entirely and returning all logs.
The correct format (which works when using fetch directly) is JSON-encoded:
filters=%5B%7B%22key%22%3A%22metadata.key%22%2C%22operator%22%3A%22eq%22%2C%22value%22%3A%5B%22requestId%22%5D%7D%2C...%5D
i.e. filters=[{"key":"metadata.key","operator":"eq","value":["requestId"]},...]
Reproduction
import Cloudflare from "cloudflare";
const client = new Cloudflare({ apiToken: "..." });
const logs = [];
for await (const log of client.aiGateway.logs.list("my-gateway", {
account_id: "...",
filters: [
{ key: "metadata.key", operator: "eq", value: ["requestId"] },
{ key: "metadata.value", operator: "eq", value: ["some-uuid"] },
],
})) {
logs.push(log);
}
console.log(logs.length);
// Expected: 1 (only matching logs)
// Actual: ALL logs in the gateway (filters ignored)
Workaround
Use fetch directly with JSON-encoded filters:
const filters = JSON.stringify([
{ key: "metadata.key", operator: "eq", value: ["requestId"] },
{ key: "metadata.value", operator: "eq", value: [requestId] },
]);
const url = `https://api.cloudflare.com/client/v4/accounts/${accountId}/ai-gateway/gateways/${gatewayId}/logs?filters=${encodeURIComponent(filters)}`;
const res = await fetch(url, {
headers: { Authorization: `Bearer ${apiToken}` },
});
Affected methods
This likely affects any method using the filters query parameter with arrays of objects:
client.aiGateway.logs.list()
client.aiGateway.logs.delete()
client.aiGateway.datasets.list() (if it uses the same filter format)
Environment
- SDK version:
cloudflare@5.2.0
- Runtime: Cloudflare Workers (also reproducible in Node.js)
Description
The
client.aiGateway.logs.list()method accepts a typedfiltersparameter (Array<LogListParams.Filter>), but the filters are silently ignored by the API becausestringifyQueryserializes them in a format the API doesn't understand.Root cause
The Cloudflare SDK overrides
stringifyQueryinsrc/index.ts:480:With
arrayFormat: 'repeat'andallowDots: true, an array of filter objects like:Gets serialized as:
This flat serialization loses the array structure — the API can't determine which
keybelongs to whichoperator/value. The result is the API ignoring the filters entirely and returning all logs.The correct format (which works when using
fetchdirectly) is JSON-encoded:i.e.
filters=[{"key":"metadata.key","operator":"eq","value":["requestId"]},...]Reproduction
Workaround
Use
fetchdirectly with JSON-encoded filters:Affected methods
This likely affects any method using the
filtersquery parameter with arrays of objects:client.aiGateway.logs.list()client.aiGateway.logs.delete()client.aiGateway.datasets.list()(if it uses the same filter format)Environment
cloudflare@5.2.0