{"record":{"id":"067992f01a7d771e","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-channel-start-with-chars-067992","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/updateIncomingIntegration.ts","lineNumber":36,"sourceCode":"\t\tupdateIncomingIntegration(\n\t\t\tintegrationId: string,\n\t\t\tintegration: INewIncomingIntegration | IUpdateIncomingIntegration,\n\t\t): IIntegration | null;\n\t}\n}\n\nfunction validateChannels(channelString: string | undefined): string[] {\n\tif (!channelString || typeof channelString.valueOf() !== 'string' || channelString.trim() === '') {\n\t\tthrow new Meteor.Error('error-invalid-channel', 'Invalid channel', {\n\t\t\tmethod: 'updateIncomingIntegration',\n\t\t});\n\t}\n\n\tconst channels = channelString.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\treturn channels;\n}\n\nexport const updateIncomingIntegration = async (\n\tuserId: string,\n\tintegrationId: string,\n\tintegration: INewIncomingIntegration | IUpdateIncomingIntegration,\n): Promise<IIntegration | null> => {\n\tconst channels = validateChannels(integration.channel);\n\n\tlet currentIntegration;\n\n\tif (await hasPermissionAsync(userId, 'manage-incoming-integrations')) {","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/integrations/incoming/updateIncomingIntegration.ts#L18-L54","documentation":"Thrown by updateIncomingIntegration's validateChannels when a comma-separated channel entry does not start with '#' or '@'. The string is split on ',', trimmed, and each segment's first character is checked against ['@', '#']. Empty segments from trailing or double commas also trigger it because channel[0] is undefined.","triggerScenarios":"channel: 'general' on update; 'general,#dev'; trailing comma '#general,'; double comma '#general,,#ops'.","commonSituations":"Edit forms that join a channel multi-select with ',' but include an empty option; hand-edited channel lists; porting from the old outgoing-integration payload style without prefixes.","solutions":["Prefix rooms with # and users with @ in every segment: '#general,#dev,@rocket.cat'","Normalize before submitting: split, trim, filter(Boolean), re-add prefixes, join","Validate in the form layer so the update call never carries malformed segments"],"exampleFix":"// before\nawait Meteor.callAsync('updateIncomingIntegration', id, { ...payload, channel: 'general, dev' });\n// after\nconst channel = payload.channel.split(',').map((c) => c.trim()).filter(Boolean).map((c) => (/^[#@]/.test(c) ? c : `#${c}`)).join(',');\nawait Meteor.callAsync('updateIncomingIntegration', id, { ...payload, channel });","handlingStrategy":"validation","validationCode":"const segments = integration.channel.split(',').map((s) => s.trim()).filter(Boolean);\nif (segments.some((s) => !['@', '#'].includes(s[0]))) throw new Error('each channel entry must start with # or @');\nawait Meteor.callAsync('updateIncomingIntegration', integrationId, { ...integration, channel: segments.join(',') });","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('updateIncomingIntegration', integrationId, integration);\n} catch (err) {\n  if (err instanceof Meteor.Error && err.error === 'error-invalid-channel-start-with-chars') { /* normalize segments and resubmit */ }\n}","preventionTips":["Share one channel-string builder between create and update paths","Filter empty segments from multi-select joins","Lint form payloads before submission"],"tags":["rocket-chat","incoming-integration","channel-validation","input-format","meteor-method"],"backgroundTag":"integration-channel-validation","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}