{"record":{"id":"3712ec32f089fd94","repo":"SigNoz/signoz","slug":"invalid-input-3712ec","errorCode":"invalid_input","errorMessage":"error updating existing filter","messagePattern":"error updating existing filter","errorType":"error_code","errorClass":"errors.base","httpStatus":400,"severity":"error","filePath":"pkg/modules/quickfilter/implquickfilter/module.go","lineNumber":90,"sourceCode":"\t}\n\n\t// Marshal filters to JSON\n\tfilterJSON, err := json.Marshal(filters)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, \"error marshalling filters\")\n\t}\n\n\t// Check if filter exists\n\texistingFilter, err := module.store.GetBySignal(ctx, orgID, signal.StringValue())\n\tif err != nil {\n\t\treturn errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, \"error checking existing filters\")\n\t}\n\n\tvar filter *quickfiltertypes.StorableQuickFilter\n\tif existingFilter != nil {\n\t\t// Update in place\n\t\tif err := existingFilter.Update(filterJSON); err != nil {\n\t\t\treturn errors.Wrapf(err, errors.TypeInvalidInput, errors.CodeInvalidInput, \"error updating existing filter\")\n\t\t}\n\t\tfilter = existingFilter\n\t} else {\n\t\t// Create new\n\t\tfilter, err = quickfiltertypes.NewStorableQuickFilter(orgID, signal, filterJSON)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, errors.TypeInvalidInput, errors.CodeInvalidInput, \"error creating new filter\")\n\t\t}\n\t}\n\n\t// Persist filter\n\tif err := module.store.Upsert(ctx, filter); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/SigNoz/signoz/blob/5069bf80b08f1f00d7e014eccc09902f9871004f/pkg/modules/quickfilter/implquickfilter/module.go#L72-L108","documentation":"UpdateQuickFilters found an existing stored filter for the (org, signal) pair and called existingFilter.Update(filterJSON), which validates the marshalled JSON against the storable filter's invariants (e.g. payload shape). A validation failure is wrapped as invalid_input with 'error updating existing filter'.","triggerScenarios":"PUT/POST quick filters for a signal that already has stored filters, where the new filter JSON fails StorableQuickFilter.Update's checks — wrong envelope shape, unknown keys, or size/format constraints.","commonSituations":"Client sending a filter payload shape that differs from what the existing row's format expects (version drift between UI and server), or a payload that violates update invariants.","solutions":["Compare your request body shape with the one the UI sends for the same signal (envelope, keys, types)","Check the wrapped underlying error for the specific validation message from Update","Update to matching client/server versions if the filter schema changed","If the stored row is stale/corrupt, delete it so the next update takes the create path"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Mirror the shape the UI sends; verify against an existing GET response\nconst existing = await getSignalFilters(orgId, signal);\nassert(filters.every(f => typeof f.key === 'string' && typeof f.value !== 'undefined'));\nawait updateQuickFilters(orgId, signal, filters);","typeGuard":"function isFilterPayload(f: unknown): f is { key: string; value: unknown; op?: string } {\n  return typeof f === 'object' && f !== null && typeof (f as any).key === 'string' && 'value' in (f as any);\n}","tryCatchPattern":"try { await updateQuickFilters(orgId, signal, filters); } catch (e) { if (e.code === 'invalid_input' && /updating existing/i.test(e.message)) { showValidationError(e.cause?.message); } else throw e; }","preventionTips":["Fetch a current filter via GET and model new payloads on its exact shape","Keep API client SDKs generated from the same server version"],"tags":["validation","invalid-input","quick-filters","golang"],"backgroundTag":"payload-validation-failed","analyzedSha":"5069bf80b08f1f00d7e014eccc09902f9871004f","analyzedAt":"2026-08-28T06:22:12.824Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}