# Serverless Compose Path Resolution and Build Issues in Monorepo Setup

**URL:** <https://forum.serverless.com/t/serverless-compose-path-resolution-and-build-issues-in-monorepo-setup/21333>\
**Category:** Serverless Framework\
**Created:** [August 8, 2025, 4:09pm UTC](https://forum.serverless.com/t/serverless-compose-path-resolution-and-build-issues-in-monorepo-setup/21333 "2025-08-08T16:09:24Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![sumit4way](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.serverless.com/sumit4way/32/8416_2.png) [@sumit4way](https://forum.serverless.com/u/sumit4way)\
**Post date:** [August 8, 2025, 4:09pm UTC](https://forum.serverless.com/t/serverless-compose-path-resolution-and-build-issues-in-monorepo-setup/21333/1 "2025-08-08T16:09:24Z")

</div>

**Environment**

\* \*\*Serverless Framework Version:\*\* v4.17.1

\* \*\*Tool:\*\* Serverless Compose

\* \*\*Operating System:\*\* Windows

\* \*\*Node.js Version:\*\* v20.9.0

\* \*\*Project Structure:\*\* Monorepo with `serverless-compose.yml` at project root

> /
> 
> ├── serverless-compose.yml
> 
> ├── serverless\_custom.yml
> 
> ├── package.json
> 
> ├── src/
> 
> │ ├── chat/
> 
> │ ├── user/
> 
> │ └── … (shared source code for all Lambdas)
> 
> └── services/
> 
> ```
> ├── compose1/ 
> 
> │ └── serverless.yml 
> 
> ├── compose2/ 
> 
> │ └── serverless.yml 
> 
> └── compose3/ 
> 
> └── serverless.yml 
> 
> ```

* * *

**Goal**

To deploy \*\*three separate services\*\* (`compose1`, `compose2`, `compose3`) using a \*\*single\*\* `serverless deploy` command, where all services share a \*\*common `src/` directory\*\* located at the project root.

\* Each service’s `serverless.yml` uses function definitions split across multiple YAML files within the `src/` folder via `${file(../../src/…)}`

\* The `src/` folder contains shared business logic and Lambda handlers.

* * *

**Problem**

When executing `serverless package` or `serverless deploy` from the \*\*project root\*\*, the process fails for all services due to \*\*path resolution issues\*\*. Specifically:

\* Each individual service (`compose1`, `compose2`, etc.) \*\*cannot resolve the shared root-level `src/` directory\*\* correctly during the \*\*build and packaging\*\* phase.

-–

_ **Specific Errors Encountered** _

**Path Resolution Failure**

```auto
Cannot resolve '${file(../../src/...)}' variable. No value is available for this variable... 

```

**Compilation Failure (Most Common)**

```auto
Compilation failed for function alias <function-name>.  

```

```auto
Please ensure you have an index file with ext .ts or .js,  

```

```auto
or have a path listed as main key in package.json 

```

**serverless-esbuild Plugin Error**

`Invalid option in context() call: "srcDir"`

**Built-in esbuild Failure**

`ENOENT: no such file or directory, open 'F:\...\services\compose1\.serverless\build\package.json'`

* * *

### \*\*Troubleshooting Attempts\*\*

We have explored multiple workarounds, but none fully resolved the issue:

1. Used both:

\* `serverless-esbuild` plugin

\* Built-in `build.esbuild` option

2. Explicitly set `srcDir` in `esbuild` config — results in plugin error.

3. Prepend the correct relative path (`src/...`) to all `handler`

4. Added dummy `package.json` files to each `services/*` directory.

5. Validated all `${file(…)}` paths relative to each `serverless.yml`.

* * *

**Conclusion**  
It seems that Serverless Compose has difficulty handling a \*\*shared `src/` folder\*\* when each service’s build context is isolated. We’re looking for a \*\*recommended, idiomatic approach\*\* to:

\* Use a \*\*single shared codebase (`src/`)\*\* for multiple services

\* Enable \*\*esbuild bundling\*\* (plugin or built-in)

\* Avoid duplication of code or `package.json` across services

\* Maintain clean separation of service definitions in `services/`

* * *

Please advise on the \*\*best practice\*\* for making this \*\*monorepo setup\*\* work reliably with:

\* \*\*Serverless Compose\*\*

\* \*\*Esbuild (plugin or built-in)\*\*

---

<div class="post-metadata">

**Author:** ![garethmcc](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.serverless.com/garethmcc/32/2276_2.png) [@garethmcc](https://forum.serverless.com/u/garethmcc)\
**Post date:** [August 11, 2025, 8:32am UTC](https://forum.serverless.com/t/serverless-compose-path-resolution-and-build-issues-in-monorepo-setup/21333/2 "2025-08-11T08:32:48Z")

</div>

Thanks for submitting the query about Serverless Compose. To better assist we would likely need to see the current configurations for serverless-compose.yml. However, if you feel like sharing that information here is too public, we can continue the conversation via [support@serverless.com](mailto:support@serverless.com). Once we are able to work through your use case you would then be more than welcome to post the solution here anyone else looking (or give us permission to).

---

<div class="post-metadata">

**Author:** ![sumit4way](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.serverless.com/sumit4way/32/8416_2.png) [@sumit4way](https://forum.serverless.com/u/sumit4way)\
**Post date:** [August 11, 2025, 1:33pm UTC](https://forum.serverless.com/t/serverless-compose-path-resolution-and-build-issues-in-monorepo-setup/21333/3 "2025-08-11T13:33:14Z")

</div>

> ```auto
> # serverless-compose.yml
> services:
> compose1:
> path: services/compose1
> compose2:
> path: services/compose2
> compose3:
> path: services/compose3
> 
> ```
> 
> ## services/compose1/serverless.yml
> 
> service: compose1  
> frameworkVersion: “4.17.1”
> 
> useDotenv: true
> 
> build:
> 
> esbuild:
> 
> ```auto
> bundle: true
> 
> minify: true
> 
> sourcemap:
> 
> type: linked
> 
> setNodeOptions: true
> 
> keepNames: true
> 
> buildConcurrency: 1
> 
> zipConcurrency: 3
> 
> watch:
> 
> pattern: \["src/\*\*/\*.(js|ts)" \]
> 
> srcDir: ../../
> 
> ```
> 
> package:
> 
> individually: true
> 
> excludeDevDependencies: true
> 
> include:
> 
> ```auto
> - templates/\*\*
> 
> ```
> 
> exclude:
> 
> ```auto
> - .git/\*\*
> 
> - .gitignore
> 
> - README.md
> 
> - package.json
> 
> - package-lock.json
> 
> - node_modules/\*\*
> 
> - test/\*\*
> 
> - .dynamodb/\*\*
> 
> - backups/\*\*
> 
> - resources/\*\*
> 
> ```
> 
> plugins:
> 
> - serverless-offline
> 
> - serverless-prune-plugin
> 
> - serverless-step-functions
> 
> custom: ${file(../../serverless\_custom.yml)}
> 
> provider:
> 
> name: aws  
> …
> 
> stages:
> 
> default:
> 
> ```auto
> params: ${ssm:/aws/reference/secretsmanager/appName/${sls:stage}}
> 
> ```
> 
> functions:
> 
> - ${file(../../src/user/setting/routes.yml)}
> 
> - ${file(../../src/subscription/config.yml)}
> 
> - ${file(../../src/subscription/routes.yml)}
> 
> - ${file(../../src/shared/system/config.yml)}
> 
> - ${file(../../src/shared/crm/config.yml)}
> 
> - ${file(../../src/shared/content/routes.yml)}
> 
> - ${file(../../src/shared/image/routes.yml)}
> 
> - ${file(../../src/shared/event/routes.yml)}
> 
> - ${file(../../src/shared/growthbook/routes.yaml)}

Hey @garethmcc , I’ve shared the serverless-compose current config. As well as one of the serverless.yml files in compose1, which is siilar to those in compose2 and compose3

Thank you for prompting about the secret key, I will make sure to share any such details privately.

---

<div class="post-metadata">

**Author:** ![glaucoleme](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.serverless.com/glaucoleme/32/7283_2.png) [@glaucoleme](https://forum.serverless.com/u/glaucoleme)\
**Post date:** [August 12, 2025, 7:53pm UTC](https://forum.serverless.com/t/serverless-compose-path-resolution-and-build-issues-in-monorepo-setup/21333/4 "2025-08-12T19:53:41Z")

</div>

As an alternative, you can avoid this issue letting npm (or similar) handle the task of sharing code among different services. Each compose has its own package.json and you can use node workspaces to share common code among them.

---

<div class="post-metadata">

**Author:** ![areales](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.serverless.com/areales/32/8453_2.png) [@areales](https://forum.serverless.com/u/areales)\
**Post date:** [October 9, 2025, 5:50pm UTC](https://forum.serverless.com/t/serverless-compose-path-resolution-and-build-issues-in-monorepo-setup/21333/5 "2025-10-09T17:50:40Z")

</div>

What was the solution for this?

I have similar issue going on.

My use case is something simple:  
Setup an image optimizer lambda function url and put it behind a CloudFront.

Initially, I tried deploying everything in a single serverless.yml configuration.

However, that doesn’t work because there is no way for me to reference the Function Url associated to the Lambda to set the origin for Cloudfront.

Then, I discovered about Serverless Compose and tried to split the deployment in a 2 step process

```auto
# Serverless Compose Configuration
# This file orchestrates the deployment of multiple serverless services in the correct order

version: '1'

services:
  # First service: Deploy Lambda function with URL
  lambda-function-url:
    path: lambda-image-optimizer

  # Second service: Deploy CloudFront distribution using the Lambda function URL
  cloudfront-distribution:
    path: cloudfront-image-optimizer
    dependsOn:
      - lambda-function-url
    params:
      # Pass the Lambda function URL from the first service
      LAMBDA_FUNCTION_URL: ${lambda-function-url:ImageOptimizerLambdaFunctionUrl}

```

But it keeps failing on the first service ` lambda-function-url`, which serverless.yml file looks like

```auto
# Lambda Function URL Service Configuration
# This service deploys only the Lambda function with URL, without CloudFront

plugins:
  - serverless-plugin-utils
  - serverless-esbuild

build:
  esbuild: false

custom:
  esbuild:
    external:
      - sharp
    packagerOptions:
      scripts:
        - npm install --os=linux --cpu=x64 sharp

provider:
  name: aws
  runtime: nodejs20.x
  stage: ${opt:stage, 'dev'}
  region: us-east-1
  timeout: 30
  memorySize: 1536
  logRetentionInDays: ${ternary( ${opt:stage, 'dev'}, prod, 14, 1 )}
  environment:
    WASABI_ENDPOINT: ${param:WASABI_ENDPOINT}
    WASABI_REGION: ${param:WASABI_REGION}
    WASABI_BUCKET_NAME: ${param:WASABI_BUCKET_NAME}
    WASABI_ACCESS_KEY_ID: ${param:WASABI_ACCESS_KEY_ID}
    WASABI_SECRET_ACCESS_KEY: ${param:WASABI_SECRET_ACCESS_KEY}
  iam:
    role:
      statements:
        - Effect: Allow
          Action:
            - s3:GetObject
            - s3:PutObject
            - s3:DeleteObject
          Resource: 
            - "arn:aws:s3:::${param:WASABI_BUCKET_NAME}/*"

functions:
  imageOptimizer:
    handler: src/handlers/cloudfrontImageOptimizer.handler
    url: true
    cors:
      origin: '*'
      headers:
        - Content-Type
        - Accept
        - Cache-Control
        - ETag
        - Last-Modified
      allowCredentials: false

# Outputs - values that will be passed to other services
resources:
  Outputs:
    ImageOptimizerLambdaFunctionUrl:
      Description: "Lambda Function URL for CloudFront Image Optimizer"
      Value: !GetAtt ImageOptimizerLambdaFunctionUrl.FunctionUrl
      Export:
        Name: ${self:service}-${self:provider.stage}-lambda-function-url

    ImageOptimizerLambdaFunctionArn:
      Description: "Lambda Function ARN for CloudFront Image Optimizer"
      Value: !GetAtt ImageOptimizerLambdaFunction.Arn
      Export:
        Name: ${self:service}-${self:provider.stage}-lambda-function-arn

```

And the error I always keep seeing is

```auto
✖ lambda-image-optimizer Build failed with 1 error:
error: Could not resolve "../src/handlers/cloudfrontImageOptimizer.ts" Results: 0 services succeeded, 1 failed, 0 skipped, 1 total Time: 9s

```

However, if I deploy directly the lamba-image-optimizer, (not via serverless compose) it works.

The project structure looks like this:  
serverless  
→ cloudfront-image-optimizer

- serverless.yml

→ lambda-image-optimizer

- serverless.yml
- src
  - handlers
    - cloudfrontImageOptimizer.ts

- package.json
- eslint.config.json
- tsconfig.json

→ serverless-compose.yml

I’ve tried also things such as:

- moving the “src” folder to the root (didn’t work)
- Updating the settings ofr the serverless.yml of the lambda function

```auto
functions:
  imageOptimizer:
    handler: ./src/handlers/cloudfrontImageOptimizer.handler

```

AND

```auto
functions:
  imageOptimizer:
    handler: ./lambda-image-optimizer/src/handlers/cloudfrontImageOptimizer.handler

```

But with no success.

What I’m going to do temporarily is to manually deploy each service, meaning I will copy and paste the function url from the lambda deployment prior to executing the cloudfront deployment. Though that is not ideal.

Any help is appreciated!
