{"record":{"id":"457d73c08b728644","repo":"Budibase/budibase","slug":"invalid-calculation-type-calculation","errorCode":null,"errorMessage":"Invalid calculation type: ${calculation}","messagePattern":"Invalid calculation type: (.+?)","errorType":"http","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/api/controllers/view/viewBuilder.ts","lineNumber":98,"sourceCode":"    },\n    count: {\n      type: \"number\",\n    },\n    sumsqr: {\n      type: \"number\",\n    },\n    avg: {\n      type: \"number\",\n    },\n  },\n}\n\nfunction validateCalculation(calculation?: string) {\n  if (\n    calculation &&\n    !Object.prototype.hasOwnProperty.call(SCHEMA_MAP, calculation)\n  ) {\n    throw new HTTPError(`Invalid calculation type: ${calculation}`, 400)\n  }\n}\n\n/**\n * Iterates through the array of filters to create a JS\n * expression that gets used in a CouchDB view.\n * @param filters - an array of filter objects\n * @returns JS Expression\n */\nfunction parseFilterExpression(filters: ViewFilter[]) {\n  const expression = []\n\n  let first = true\n  for (let filter of filters) {\n    if (!first && filter.conjunction) {\n      expression.push(tokenOrThrow(\"conjunction\", filter.conjunction))\n    }\n","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/api/controllers/view/viewBuilder.ts#L80-L116","documentation":"Table views support a fixed set of calculation/aggregation types defined by SCHEMA_MAP (e.g. COUNT, SUM, MIN, MAX, AVG). validateCalculation throws HTTP 400 when a calculation string is supplied that is not a key of SCHEMA_MAP.","triggerScenarios":"Creating/saving a table view (v2) with a calculation field set to an unsupported or misspelled value such as \"count\" lowercase, \"average\", \"median\", or null-adjacent typos.","commonSituations":"API clients building views with wrong enum casing; migrations from older view formats with renamed calculations; UI integrations passing a raw user string as calculation.","solutions":["Use a supported calculation exactly as defined in SCHEMA_MAP (e.g. COUNT, SUM, MIN, MAX, AVG)","Match the enum casing (uppercase) when constructing the view payload","Fetch an existing valid view (GET) and copy its calculation value as a reference"],"exampleFix":"// before\n{ calculation: \"average\", field: \"price\" }\n// after\n{ calculation: \"AVG\", field: \"price\" }","handlingStrategy":"validation","validationCode":"const CALCULATIONS = [\"COUNT\",\"SUM\",\"MIN\",\"MAX\",\"AVG\"]\nfunction assertCalculation(calc) {\n  if (calc && !CALCULATIONS.includes(calc)) {\n    throw new Error(`calculation must be one of ${CALCULATIONS.join(\",\")}`)\n  }\n}","typeGuard":"const isCalculation = (c) => typeof c === \"string\" && [\"COUNT\",\"SUM\",\"MIN\",\"MAX\",\"AVG\"].includes(c)","tryCatchPattern":"try {\n  await api.saveView({ calculation, field, tableId })\n} catch (e) {\n  if (e?.status === 400 && /Invalid calculation type/.test(e.message)) {\n    // map to the closest supported calculation and retry\n  } else throw e\n}","preventionTips":["Reference the calculation enum from @budibase/types instead of raw strings","Normalize user-supplied aggregations to uppercase supported values","Reject unsupported stats (median, stddev) at the UI layer","Copy calculation values from existing valid views when scripting"],"tags":["view","calculation","validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}