Skip to content

Using uv during packing can lead to stale code deployment #13169

@michalszelagsonos

Description

@michalszelagsonos

Issue description

This is more of a side effect of how uv works and how it is used in sls but the effect can be quite nasty so I am opening this as a bug for documentation.

I am using uv as the package manager in my project and this is the configuration I have:

custom:
  pythonRequirements:
    useUv: true
    installer: uv
    slim: true
    strip: false
    useDownloadCache: true
    useStaticCache: false

When running serverless package, this command is executed under the hood to install the dependencies into a folder which includes the local package specified as . in generated requirements.txt.

uv pip install --target /Users/michal.szelag/workspace/sipi-trigger/.serverless/requirements -r /Users/michal.szelag/workspace/sipi-trigger/.serverless/requirements/requirements.txt --cache-dir /Users/michal.szelag/Library/Caches/serverless-python-requirements/downloadCacheslspyc

Generated requirements.txt for reference:

.
boto3==1.41.4
botocore==1.41.4
certifi==2025.11.12
charset-normalizer==3.4.4
idna==3.11
jmespath==1.0.1
python-dateutil==2.9.0.post0
pyyaml==6.0.3
requests==2.32.5
s3transfer==0.15.0
schema==0.7.8
six==1.17.0
urllib3==2.5.0

The problem is, uv caches the content of the local package so when it is told again to install the local package specified with . it uses the cached entry, not what is in the workspace. The effect is, you made a code change, you deploy, and the change isn't deployed.

This is how uv works. Users that use pip may also hit this problem (I didn't test that).

The good news is there are 2 ways to force uv to do the right thing and they should be documented.

Option 1 - add the following to serverless.yaml or equivalent to force the reinstall:

custom:
  pythonRequirements:
    pipCmdExtraArgs:
      - --reinstall-package <your package name>

If serverless can figure out the package name and do it for the user, even better.

Option 2 - add this to pyproject.toml to force the install:

[tool.uv]
reinstall-package = ["my-package-name"]

FWIW, I opted for option 2 since it keeps the package name in the same file so odds are smaller they will drift. The name is now in 2 places in the file but that's better than 2 places across 2 files.

Context

No response

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions