{"record":{"id":"7b59bbc25c424052","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-channel-start-with-chars-7b59bb","errorCode":"error-invalid-channel-start-with-chars","errorMessage":"Invalid channel. Start with @ or #","messagePattern":"Invalid channel\\. Start with @ or #","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/meteor-methods/integrations/incoming/addIncomingIntegration.ts","lineNumber":69,"sourceCode":"\t}\n\n\tif (!integration.channel || typeof integration.channel.valueOf() !== 'string') {\n\t\tthrow new Meteor.Error('error-invalid-channel', 'Invalid channel', {\n\t\t\tmethod: 'addIncomingIntegration',\n\t\t});\n\t}\n\n\tif (integration.channel.trim() === '') {\n\t\tthrow new Meteor.Error('error-invalid-channel', 'Invalid channel', {\n\t\t\tmethod: 'addIncomingIntegration',\n\t\t});\n\t}\n\n\tconst channels = integration.channel.split(',').map((channel) => channel.trim());\n\n\tfor (const channel of channels) {\n\t\tif (!validChannelChars.includes(channel[0])) {\n\t\t\tthrow new Meteor.Error('error-invalid-channel-start-with-chars', 'Invalid channel. Start with @ or #', {\n\t\t\t\tmethod: 'updateIncomingIntegration',\n\t\t\t});\n\t\t}\n\t}\n\n\tif (!integration.username || typeof integration.username.valueOf() !== 'string' || integration.username.trim() === '') {\n\t\tthrow new Meteor.Error('error-invalid-username', 'Invalid username', {\n\t\t\tmethod: 'addIncomingIntegration',\n\t\t});\n\t}\n\n\tif (integration.script?.trim()) {\n\t\tvalidateScriptEngine(integration.scriptEngine ?? 'isolated-vm');\n\t}\n\n\tconst user = await Users.findOneByUsername(integration.username, { projection: { _id: 1 } });\n\n\tif (!user) {","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/integrations/incoming/addIncomingIntegration.ts#L51-L87","documentation":"Thrown by addIncomingIntegration when any comma-separated channel entry does not start with '#' or '@' (validChannelChars = ['@', '#']). The string is split on ',' and each segment trimmed, so a segment must begin with # (room target) or @ (direct-message target). An empty segment - caused by a trailing comma or a double comma - also triggers this, because channel[0] is undefined. Quirk: the error's details.method says 'updateIncomingIntegration' even on add (copy-paste in the source), so do not key handling on details.method here.","triggerScenarios":"channel: 'general' (no prefix); 'general, #dev' (first entry unprefixed); '#general,' (trailing comma produces an empty segment); '#general,,#dev' (double comma).","commonSituations":"Users typing bare room names copied from the UI title; CSV-style input with a trailing comma; a form that joins selected channels with ',' but leaves an empty selection in the list.","solutions":["Prefix every room with # and every direct target with @, e.g. '#general,#dev,@rocket.cat'","Filter out empty segments before submitting: channel.split(',').map(s => s.trim()).filter(Boolean).join(',')","Remove trailing/double commas from user input in the form layer"],"exampleFix":"// before\nconst channel = ['general', 'dev'].join(','); // 'general,dev'\n// after\nconst channel = ['general', 'dev'].map((c) => c.trim() ? `#${c.trim().replace(/^[#@]/, '')}` : '').filter(Boolean).join(','); // '#general,#dev'","handlingStrategy":"validation","validationCode":"const validChannelChars = ['@', '#'];\nconst segments = String(integration.channel ?? '').split(',').map((s) => s.trim());\nconst invalid = segments.filter((s) => !validChannelChars.includes(s[0]));\nif (segments.some((s) => !s) || invalid.length) throw new Error(`channel entries must start with # or @: ${invalid.join(', ')}`);\nawait Meteor.callAsync('addIncomingIntegration', integration);","typeGuard":"const isValidChannelList = (c: unknown): c is string =>\n  typeof c === 'string' && c.trim() !== '' &&\n  c.split(',').every((s) => ['@', '#'].includes(s.trim()[0]));","tryCatchPattern":"try {\n  await Meteor.callAsync('addIncomingIntegration', integration);\n} catch (err) {\n  if (err instanceof Meteor.Error && err.error === 'error-invalid-channel-start-with-chars') { /* highlight offending entry; note details.method is mislabeled 'updateIncomingIntegration' here */ }\n}","preventionTips":["Build channel strings from typed selections that already carry the #/@ prefix","Filter empty segments before join","Unit-test the join helper against trailing/double commas"],"tags":["rocket-chat","incoming-integration","meteor-method","channel-validation","input-format"],"backgroundTag":"integration-channel-validation","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}