{"record":{"id":"b28c05c734a4b6df","repo":"FlowiseAI/Flowise","slug":"at-least-one-field-to-update-must-be-provided","errorCode":null,"errorMessage":"At least one field to update must be provided","messagePattern":"At least one field to update must be provided","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/components/nodes/tools/MicrosoftTeams/core.ts","lineNumber":257,"sourceCode":"\n        super({ ...toolInput, accessToken: args.accessToken, defaultParams: args.defaultParams })\n    }\n\n    protected async _call(arg: any): Promise<string> {\n        const params = { ...arg, ...this.defaultParams }\n        const { teamId, channelId, displayName, description } = params\n\n        if (!teamId || !channelId) {\n            throw new Error('Both Team ID and Channel ID are required')\n        }\n\n        try {\n            const body: any = {}\n            if (displayName) body.displayName = displayName\n            if (description) body.description = description\n\n            if (Object.keys(body).length === 0) {\n                throw new Error('At least one field to update must be provided')\n            }\n\n            const endpoint = `/teams/${teamId}/channels/${channelId}`\n            await this.makeTeamsRequest(endpoint, 'PATCH', body)\n\n            return this.formatResponse(\n                {\n                    success: true,\n                    message: 'Channel updated successfully'\n                },\n                params\n            )\n        } catch (error) {\n            return this.formatResponse(`Error updating channel: ${error}`, params)\n        }\n    }\n}\n","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/components/nodes/tools/MicrosoftTeams/core.ts#L239-L275","documentation":"Thrown INSIDE the try block of UpdateChannelTool._call (core.ts:256) when both displayName and description are absent, so the constructed body object is empty. Unlike the ID checks above, this throw IS caught by the catch at core.ts:270 and converted into a formatResponse error string — so the tool returns a string like '{\"...\":\"Error updating channel: Error: At least one field to update must be provided\"}...{...params}' rather than rejecting. Callers must JSON-parse and inspect the success/error shape, not just await the call.","triggerScenarios":"update_channel invoked with valid IDs but with neither displayName nor description; both optional fields explicitly set to undefined or empty string; defaultParams provides only IDs.","commonSituations":"Agent calls update_channel to 'change something' without specifying what; UI no-op submit; replay/restore script that diffs and finds no diff but calls update anyway.","solutions":["Pass at least one of displayName or description as a non-empty string.","At the call site, short-circuit: if (!newDisplayName && !newDescription) return skip.","Parse the tool's return string and check for an 'Error updating channel' marker before treating the call as successful.","Refactor: move this check above the try block and throw, so all validation errors behave consistently."],"exampleFix":"// before — throw inside try, swallowed into a response string\nif (Object.keys(body).length === 0) {\n    throw new Error('At least one field to update must be provided')\n}\n\n// after — guard before constructing the request, return a structured error\nif (!displayName && !description) {\n    return this.formatResponse(\n        { success: false, error: 'At least one field to update must be provided' },\n        params\n    )\n}","handlingStrategy":"validation","validationCode":"function shouldUpdateChannel(input: { displayName?: string; description?: string }): boolean {\n  return Boolean((input.displayName && input.displayName.trim()) || (input.description && input.description.trim()))\n}\n\n// usage\nif (!shouldUpdateChannel(input)) {\n  return { success: true, message: 'No fields to update; skipping' }\n}","typeGuard":"function hasChannelUpdateField(x: unknown): boolean {\n  if (typeof x !== 'object' || x === null) return false\n  const { displayName, description } = x as any\n  return (typeof displayName === 'string' && displayName.trim() !== '') ||\n         (typeof description === 'string' && description.trim() !== '')\n}","tryCatchPattern":"// This error is swallowed into a response string, so parse instead of catch\nconst raw = await updateChannelTool.invoke(input)\nconst parsed = JSON.parse(raw.split(TOOL_ARGS_PREFIX)[0])\nif (!parsed.success || /Error updating channel/.test(JSON.stringify(parsed))) {\n  // handle the no-op case\n}","preventionTips":["Short-circuit at the call site when there is nothing to update — do not call the tool.","Remember 446 is thrown inside try and converted to a response string, so try/catch at the caller will not see it.","Parse the tool's return string and inspect for 'Error updating channel' before declaring success.","Add a unit test for the empty-body case to lock in current behavior."],"tags":["validation","microsoft-teams","no-op","channel","update","swallowed-error"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}