{"record":{"id":"8b9a6a694f2effb7","repo":"n8n-io/n8n","slug":"removefieldscontaining-expected-non-empty-strin","errorCode":null,"errorMessage":"removeFieldsContaining(): expected non-empty string arg","messagePattern":"removeFieldsContaining\\(\\): expected non-empty string arg","errorType":"exception","errorClass":"ExpressionExtensionError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/expression-runtime/src/extensions/object-extensions.ts","lineNumber":39,"sourceCode":"\tconst [name] = extraArgs;\n\treturn name in value;\n}\n\nfunction removeField(value: object, extraArgs: string[]): object {\n\tconst [name] = extraArgs;\n\tif (name in value) {\n\t\tconst newObject = { ...value };\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n\t\tdelete (newObject as any)[name];\n\t\treturn newObject;\n\t}\n\treturn value;\n}\n\nfunction removeFieldsContaining(value: object, extraArgs: string[]): object {\n\tconst [match] = extraArgs;\n\tif (typeof match !== 'string' || match === '') {\n\t\tthrow new ExpressionExtensionError('removeFieldsContaining(): expected non-empty string arg');\n\t}\n\tconst newObject = { ...value };\n\tfor (const [key, val] of Object.entries(value)) {\n\t\tif (typeof val === 'string' && val.includes(match)) {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n\t\t\tdelete (newObject as any)[key];\n\t\t}\n\t}\n\treturn newObject;\n}\n\nfunction keepFieldsContaining(value: object, extraArgs: string[]): object {\n\tconst [match] = extraArgs;\n\tif (typeof match !== 'string' || match === '') {\n\t\tthrow new ExpressionExtensionError(\n\t\t\t'argument of keepFieldsContaining must be a non-empty string',\n\t\t);\n\t}","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/expression-runtime/src/extensions/object-extensions.ts#L21-L57","documentation":"The object extension `removeFieldsContaining(match)` deletes object fields whose STRING value contains `match`. It throws when `match` is not a string or is the empty string, since an empty match would match (and delete) every string field — a destructive footgun the guard explicitly prevents.","triggerScenarios":"`.removeFieldsContaining('')` or `.removeFieldsContaining(123)` or `.removeFieldsContaining(undefined)`.","commonSituations":"A dynamic match value pulled from upstream that happens to be empty; a numeric match where a string was intended; field rename left `match` undefined.","solutions":["Pass a non-empty string literal or expression: `.removeFieldsContaining('tmp_')`.","Guard the match value in a Code node and only call the extension when it is a non-empty string.","If you genuinely want to remove all string fields, iterate and delete them explicitly in a Code node."],"exampleFix":"// before\n{{ $json.row.removeFieldsContaining($json.maybeEmpty) }}\n// after\n{{ $json.row.removeFieldsContaining($json.maybeEmpty || 'UNDEFINED') }}","handlingStrategy":"validation","validationCode":"const match = $json.match;\nif (typeof match !== 'string' || match === '') {\n  throw new Error('removeFieldsContaining(): match must be a non-empty string');\n}\nreturn $json;","typeGuard":"const isNonEmptyString = (v: unknown): v is string => typeof v === 'string' && v.length > 0;","tryCatchPattern":null,"preventionTips":["Pass a non-empty string match.","Guard dynamic match values in a Code node before the expression.","Coerce numerics with `String(...)` if a numeric substring match is intended."],"tags":["expression","object","string","validation","argument-shape"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}