{"record":{"id":"568695e5d87f0b70","repo":"n8n-io/n8n","slug":"parameter-key-must-be-a-string-568695","errorCode":null,"errorMessage":"Parameter ${key} must be a string","messagePattern":"Parameter (.+?) must be a string","errorType":"exception","errorClass":"NodeOperationError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreMongoDBAtlas/VectorStoreMongoDBAtlas.node.ts","lineNumber":228,"sourceCode":"\t\tthrow new NodeOperationError(this.getNode(), `Error: ${error.message}`);\n\t} finally {\n\t\tvoid client.close().catch(() => {});\n\t}\n}\n\n/**\n * Get a parameter from the context.\n * @param key - The key of the parameter.\n * @param context - The context.\n * @param itemIndex - The index.\n * @returns The value.\n */\nexport function getParameter(key: string, context: IFunctionsContext, itemIndex: number): string {\n\tconst value = context.getNodeParameter(key, itemIndex, '', {\n\t\textractValue: true,\n\t}) as string;\n\tif (typeof value !== 'string') {\n\t\tthrow new NodeOperationError(context.getNode(), `Parameter ${key} must be a string`);\n\t}\n\treturn value;\n}\n\nexport const getCollectionName = getParameter.bind(null, MONGODB_COLLECTION_NAME);\nexport const getVectorIndexName = getParameter.bind(null, VECTOR_INDEX_NAME);\nexport const getEmbeddingFieldName = getParameter.bind(null, EMBEDDING_NAME);\nexport const getMetadataFieldName = getParameter.bind(null, METADATA_FIELD_NAME);\n\nexport function getFilterValue<T>(\n\tname: string,\n\tcontext: IExecuteFunctions | ISupplyDataFunctions,\n\titemIndex: number,\n): T | undefined {\n\tconst options: IDataObject = context.getNodeParameter('options', itemIndex, {});\n\n\tif (options[name]) {\n\t\tif (typeof options[name] === 'string') {","sourceCodeStart":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreMongoDBAtlas/VectorStoreMongoDBAtlas.node.ts#L210-L246","documentation":"Type-validation NodeOperationError from the `getParameter` helper used by the MongoDB Atlas node. After extracting the parameter with `extractValue: true` and casting to `string`, it re-checks at runtime that the value is actually a string. The bound callers (`getCollectionName`, `getVectorIndexName`, `getEmbeddingFieldName`, `getMetadataFieldName`) all rely on this guard.","triggerScenarios":"Any of the four bound parameters (collection name, vector index name, embedding field, metadata field) holds a non-string value at execution time — an expression returned an object/number, or the workflow JSON stored an object envelope that `extractValue` did not unwrap.","commonSituations":"Expression `={{ $json.someObject }}` bound to a field that should be a string; workflow migrated from a node typeVersion where the parameter shape differed; field left as the RLC envelope object.","solutions":["Open the node and set the offending field to a literal string or a string-returning expression.","If using an expression, coerce to string: `={{ String($json.field) }}`.","Upgrade the node typeVersion so parameter extraction matches the current contract.","Inspect the saved workflow JSON for the named field and correct its value type."],"exampleFix":"// before\nexport function getParameter(key: string, context: IFunctionsContext, itemIndex: number): string {\n  const value = context.getNodeParameter(key, itemIndex, '', { extractValue: true }) as string;\n  if (typeof value !== 'string') {\n    throw new NodeOperationError(context.getNode(), `Parameter ${key} must be a string`);\n  }\n  return value;\n}\n\n// after: include the received type and value in the message for fast diagnosis\nif (typeof value !== 'string') {\n  throw new NodeOperationError(context.getNode(), `Parameter ${key} must be a string`, {\n    itemIndex,\n    description: `Received ${typeof value}: ${JSON.stringify(value)}`,\n  });\n}","handlingStrategy":"type-guard","validationCode":"// Centralize string-parameter resolution and coerce common envelopes.\nfunction getStringParam(context: IFunctionsContext, key: string, itemIndex: number): string {\n  const raw = context.getNodeParameter(key, itemIndex, '', { extractValue: true });\n  if (typeof raw === 'string') return raw;\n  if (raw && typeof raw === 'object' && typeof (raw as { value?: unknown }).value === 'string') {\n    return (raw as { value: string }).value;\n  }\n  throw new NodeOperationError(context.getNode(), `Parameter ${key} must be a string`, {\n    itemIndex, description: `Received ${typeof raw}: ${JSON.stringify(raw)}`,\n  });\n}","typeGuard":"function isNonEmptyString(value: unknown): value is string {\n  return typeof value === 'string' && value.length > 0;\n}","tryCatchPattern":"const value = context.getNodeParameter(key, itemIndex, '', { extractValue: true });\nif (!isNonEmptyString(value)) {\n  throw new NodeOperationError(context.getNode(), `Parameter ${key} must be a string`, { itemIndex });\n}","preventionTips":["Coerce expression results with String(...) when binding to these fields.","Upgrade node typeVersion after a parameter-shape change.","Validate the saved workflow JSON for parameter types before import."],"tags":["mongodb-atlas","vector-store","type-validation","parameter","node-operation-error","langchain"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}