{"record":{"id":"e6b8125767e53291","repo":"chatwoot/chatwoot","slug":"custom-attribute-is-required","errorCode":null,"errorMessage":"Custom attribute is required","messagePattern":"Custom attribute is required","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"app/javascript/entrypoints/sdk.js","lineNumber":149,"sourceCode":"      window.$chatwoot.user = user;\n      IFrameHelper.sendMessage('set-user', { identifier, user });\n\n      setCookieWithDomain(userCookieName, hashToBeStored, {\n        baseDomain,\n      });\n    },\n\n    setCustomAttributes(customAttributes = {}) {\n      if (!customAttributes || !Object.keys(customAttributes).length) {\n        throw new Error('Custom attributes should have atleast one key');\n      } else {\n        IFrameHelper.sendMessage('set-custom-attributes', { customAttributes });\n      }\n    },\n\n    deleteCustomAttribute(customAttribute = '') {\n      if (!customAttribute) {\n        throw new Error('Custom attribute is required');\n      } else {\n        IFrameHelper.sendMessage('delete-custom-attribute', {\n          customAttribute,\n        });\n      }\n    },\n\n    setConversationCustomAttributes(customAttributes = {}) {\n      if (!customAttributes || !Object.keys(customAttributes).length) {\n        throw new Error('Custom attributes should have atleast one key');\n      } else {\n        IFrameHelper.sendMessage('set-conversation-custom-attributes', {\n          customAttributes,\n        });\n      }\n    },\n\n    deleteConversationCustomAttribute(customAttribute = '') {","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/chatwoot/chatwoot/blob/ed230f9bc068e7a13dd5c0404d5465a204b68d4c/app/javascript/entrypoints/sdk.js#L131-L167","documentation":"Thrown by the Chatwoot website SDK (window.$chatwoot) when deleteCustomAttribute() is called with an empty, undefined, or whitespace-only attribute key. The SDK validates arguments client-side before forwarding a 'delete-custom-attribute' postMessage to the chat widget iframe. It exists because deleting an attribute requires knowing which attribute key to remove.","triggerScenarios":"Calling $chatwoot.deleteCustomAttribute('') , $chatwoot.deleteCustomAttribute(), or passing a variable that is undefined/null/empty string before the widget has the attribute set. The default parameter is '' so omitting the argument always throws.","commonSituations":"Dynamic code that derives the attribute key from user input or a data map and passes a missing key; calling delete right after page load with a value not yet populated; typos in the method name arguments; calling before setCustomAttributes ever stored the key.","solutions":["Pass a non-empty attribute key string that was previously set via setCustomAttributes, e.g. $chatwoot.deleteCustomAttribute('plan_id')","If the key comes from a variable, guard it: if (key) $chatwoot.deleteCustomAttribute(key)","Verify the attribute was actually set earlier with setCustomAttributes / setConversationCustomAttributes before deleting"],"exampleFix":"// before\n$chatwoot.deleteCustomAttribute(user.plan); // throws if user.plan is undefined\n\n// after\nif (user.plan) {\n  $chatwoot.deleteCustomAttribute(user.plan);\n}","handlingStrategy":"validation","validationCode":"const key = 'plan_id';\nif (typeof key === 'string' && key.trim().length > 0) {\n  window.$chatwoot.deleteCustomAttribute(key);\n}","typeGuard":"function isNonEmptyString(v) {\n  return typeof v === 'string' && v.trim().length > 0;\n}","tryCatchPattern":"try {\n  window.$chatwoot.deleteCustomAttribute(key);\n} catch (e) {\n  console.warn('chatwoot: skipping delete, invalid attribute key', e.message);\n}","preventionTips":["Only call delete for keys you previously set via setCustomAttributes","Filter falsy keys before delete loops: keys.filter(Boolean)","Treat a thrown validation error from the SDK as a no-op signal, not a crash: guard inputs before calling"],"tags":["chatwoot-sdk","custom-attributes","argument-validation","javascript"],"backgroundTag":"missing-required-argument","analyzedSha":"ed230f9bc068e7a13dd5c0404d5465a204b68d4c","analyzedAt":"2026-08-21T12:45:25.920Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}