{"record":{"id":"4c48a89f0711d395","repo":"serverless/serverless","slug":"legacy-configuration-property-merge-invalid-input","errorCode":"LEGACY_CONFIGURATION_PROPERTY_MERGE_INVALID_INPUT","errorMessage":"Non-object value specified in ${key} array: ${value}","messagePattern":"Non-object value specified in (.+?) array: (.+?)","errorType":"error_code","errorClass":"ServerlessError","httpStatus":null,"severity":"error","filePath":"packages/serverless/lib/classes/service.js","lineNumber":246,"sourceCode":"        this.functions[functionName].events = []\n      }\n\n      if (!functionObj.name) {\n        this.functions[functionName].name =\n          `${this.service}-${stageNameForFunction}-${functionName}`\n      }\n    })\n  }\n\n  mergeArrays() {\n    ;['resources', 'functions'].forEach((key) => {\n      if (Array.isArray(this[key])) {\n        this[key] = this[key].reduce((memo, value) => {\n          if (value) {\n            if (typeof value === 'object') {\n              return _.merge(memo, value)\n            }\n            throw new ServerlessError(\n              `Non-object value specified in ${key} array: ${value}`,\n              'LEGACY_CONFIGURATION_PROPERTY_MERGE_INVALID_INPUT',\n            )\n          }\n\n          return memo\n        }, {})\n      }\n    })\n  }\n\n  async validate() {\n    const userConfig = this.initialServerlessConfig\n\n    // Ensure to validate normalized (after mergeArrays) input\n    if (userConfig.functions) userConfig.functions = this.functions\n    if (userConfig.resources) userConfig.resources = this.resources\n","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/serverless/serverless/blob/b9d7ea51c8cce57cff1207964b9b71123673081f/packages/serverless/lib/classes/service.js#L228-L264","documentation":"`mergeArrays` supports a legacy form where `resources` or `functions` is an array of objects to deep-merge with lodash `_.merge`. If any element of that array is truthy but not an object (a string, number, etc.), the merge cannot proceed and this error throws. Falsy elements are silently skipped.","triggerScenarios":"`resources: [...]` or `functions: [...]` where at least one element is a non-null primitive, e.g. `resources: ['description', { Resources: {...} }]`.","commonSituations":"Composing multiple CloudFormation snippet files where one file accidentally exports a string comment; YAML lists that mixed a scalar header with object fragments; hand-merged configs from pull requests that pasted a string into the resources array.","solutions":["Ensure every element of the `resources`/`functions` array is an object.","Move descriptive strings into a `Description:` CloudFormation property inside an object, not as a bare array item.","Use `serverless print` to dump the array and find the offending scalar element."],"exampleFix":"# before\nresources:\n  - 'my stack'\n  - Resources:\n      MyBucket:\n        Type: AWS::S3::Bucket\n# after\nresources:\n  - Description: 'my stack'\n  - Resources:\n      MyBucket:\n        Type: AWS::S3::Bucket","handlingStrategy":"validation","validationCode":"for (const key of ['resources', 'functions']) {\n  if (Array.isArray(config[key])) {\n    config[key].forEach((el, i) => {\n      if (el && typeof el !== 'object') {\n        throw new Error(`${key}[${i}] must be an object, got ${typeof el}`)\n      }\n    })\n  }\n}","typeGuard":"const isValidArrayForm = (v) => !Array.isArray(v) || v.every((el) => el == null || typeof el === 'object')","tryCatchPattern":"try {\n  service.mergeArrays()\n} catch (e) {\n  if (e.code === 'LEGACY_CONFIGURATION_PROPERTY_MERGE_INVALID_INPUT') { console.error('Remove non-object entries from resources/functions arrays'); process.exit(1) }\n  throw e\n}","preventionTips":["Prefer the modern object form of resources/functions over the legacy array form.","If using array form for composition, keep every element a CloudFormation fragment object.","Move free-text descriptions into a `Description:` property inside an object."],"tags":["config","resources","functions","legacy","merge","type-mismatch"],"backgroundTag":null,"analyzedSha":"b9d7ea51c8cce57cff1207964b9b71123673081f","analyzedAt":"2026-08-13T04:14:40.386Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}