langfuse/langfuse · error · InvalidRequestError
Invalid JSON in filter parameter
Error message
Invalid JSON in filter parameter
What it means
Thrown by the scores API filter parameter parser when the filter query-string value is present but is not valid JSON. The string is JSON.parse'd inside a zod transform; a parse failure (other than a re-thrown InvalidRequestError) is converted to this message.
Source
Thrown at packages/shared/src/features/scores/interfaces/api/shared.ts:69
.transform((str) => str.split(",").map((id) => id.trim())) // Split the comma-separated string
.refine((arr) => arr.every((id) => typeof id === "string"), {
message: "Each score ID must be a string",
})
.nullish(),
fields: commaSeparatedEnumArray(SCORE_FIELD_GROUPS, null, {
unknownValues: "filter",
}),
filter: z
.string()
.optional()
.transform((str) => {
if (!str) return undefined;
try {
const parsed = JSON.parse(str);
return parsed;
} catch (e) {
if (e instanceof InvalidRequestError) throw e;
throw new InvalidRequestError("Invalid JSON in filter parameter");
}
})
.pipe(z.array(singleFilter).optional()),
});
// POST /scores
// Roughly mirrors ScoreBody in `packages/shared/src/server/ingestion/types.ts`;
// keep them in sync for fields that cross both surfaces.
export const PostScoresBody = applyScoreValidation(
PostScoreBodyFoundationSchema.extend({
source: PublicApiCreateScoreSourceDomain.default(ScoreSourceEnum.API),
}).and(
z.discriminatedUnion("dataType", [
z.object({
value: z.number(),
dataType: z.literal("NUMERIC"),
configId: z.string().nullish(),
}),View on GitHub (pinned to 59d92c7cf3)
Solutions
- URL-encode a proper JSON array for filter, e.g. filter=%5B%7B%22type%22...%5D
- Validate/craft the JSON with JSON.stringify on the client rather than by hand
- Omit the filter parameter entirely if no filtering is needed (undefined is allowed)
Example fix
// before GET /api/public/scores?filter=environment=production // after GET /api/public/scores?filter=%5B%7B%22column%22%3A%22environment%22%2C%22type%22%3A%22stringOptions%22%2C%22operator%22%3A%22%3D%22%2C%22value%22%3A%22production%22%7D%5D
Defensive patterns
Strategy: validation
Validate before calling
let filter: unknown;
if (rawFilterParam) { try { filter = JSON.parse(rawFilterParam); } catch { return badRequest('filter must be a JSON array'); } } Type guard
const isValidFilterJson = (s: string) => { try { const v = JSON.parse(s); return Array.isArray(v); } catch { return false; } }; Try / catch
catch (e) { if (e instanceof InvalidRequestError && e.message === 'Invalid JSON in filter parameter') { /* re-encode filter with encodeURIComponent(JSON.stringify(arr)) */ } throw e; } Prevention
- Always encodeURIComponent(JSON.stringify(filterArray)) when building the URL
- Never send key=value syntax in the filter param
When it happens
Trigger: GET /api/public/scores?filter=environment%3Dproduction or any non-JSON filter string like filter=abc instead of filter=[{"type":"stringOptions",...}].
Common situations: Passing key=value style filters instead of a JSON array; broken URL encoding of quotes/brackets; trailing commas in hand-written JSON.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- INVALID_RESULT
- Invalid operator: " + operator
- Invalid Bedrock credentials. Expected AWS access key JSON or
- Invalid filter type '${filter.type}' for legacy score column
- Invalid filter type '${frontEndFilter.type}' for column '${f
AI-assisted analysis of langfuse/langfuse@59d92c7cf3 (2026-08-27).
Data as JSON: /api/errors/283dee904a75fa9c.
Report an issue: GitHub.