{"record":{"id":"3bab144821a0f728","repo":"octobercms/october","slug":"inspector-unique-key-is-a-required-string","errorCode":null,"errorMessage":"Inspector unique key is a required string","messagePattern":"Inspector unique key is a required string","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"modules/backend/vuecomponents/inspector/assets/js/classes/host.js","lineNumber":20,"sourceCode":"    showModal(title, obj, dataSchema, uniqueId, options, parentObj) {\n        if (typeof title !== 'string' || !title.length) {\n            throw new Error('Inspector title is a required string');\n        }\n\n        if (typeof obj !== 'object') {\n            throw new Error('Inspector Object must be an object');\n        }\n\n        if (parentObj !== undefined && typeof parentObj !== 'object') {\n            throw new Error('Inspector Parent Object must be an object');\n        }\n\n        if (!Array.isArray(dataSchema)) {\n            throw new Error('Inspector data schema must be an array');\n        }\n\n        if (typeof uniqueId !== 'string' || !uniqueId.length) {\n            throw new Error('Inspector unique key is a required string');\n        }\n\n        if (options) {\n            if (typeof options !== 'object') {\n                throw new Error('options must be an object');\n            }\n\n            if (options.buttonText && typeof options.buttonText !== 'string') {\n                throw new Error('options.buttonText must be a string');\n            }\n\n            if (options.size && typeof options.size !== 'string') {\n                throw new Error('options.size must be a string');\n            }\n\n            if (options.description && typeof options.description !== 'string') {\n                throw new Error('options.description must be a string');\n            }","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/octobercms/october/blob/b608633a7e8922487d91a8161499020121c3b3bf/modules/backend/vuecomponents/inspector/assets/js/classes/host.js#L2-L38","documentation":"The `uniqueId` argument of showModal() must be a non-empty string; the inspector uses it to key its Vue application, event channels, and change tracking, so a missing or numeric id breaks identity. Passing a numeric database id is the classic trigger — JavaScript numbers are not strings, and the check is strict.","triggerScenarios":"showModal(title, obj, schema, model.id) where id is a number; omitting uniqueId so the `options` value shifts into its position; passing '' from a not-yet-generated key.","commonSituations":"Using record primary keys as inspector ids without String(); generating ids per modal open and racing initialization; positional-argument mistakes after the signature gained `options`.","solutions":["Coerce ids: showModal(title, obj, schema, String(record.id)).","Generate a key once per modal instance (e.g. 'inspector-' + Date.now()) and pass it consistently.","Recheck argument order: (title, obj, dataSchema, uniqueId, options, parentObj)."],"exampleFix":"// before\nhost.showModal(title, obj, schema, record.id);\n\n// after\nhost.showModal(title, obj, schema, String(record.id));","handlingStrategy":"validation","validationCode":"const uniqueId = typeof rawId === 'string' && rawId.length ? rawId : String(rawId);\nhost.showModal(title, obj, schema, uniqueId);","typeGuard":"function isInspectorUniqueId(value) {\n    return typeof value === 'string' && value.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Coerce numeric ids with String() before passing","Generate one stable key per modal instance","Recheck positional order: (title, obj, dataSchema, uniqueId, options, parentObj)"],"tags":["inspector","argument-validation","unique-id","modal","vue"],"backgroundTag":"invalid-argument-type","analyzedSha":"b608633a7e8922487d91a8161499020121c3b3bf","analyzedAt":"2026-08-21T04:24:57.515Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}