pypa/pip · error · CommandError

List format 'freeze' cannot be used with the --outdated…

Error message

List format 'freeze' cannot be used with the --outdated option.

What it means

Raised by pip list when --outdated is combined with the freeze output format (--format freeze). The freeze format emits `name==version` lines intended for requirements files and has no concept of 'latest version' or up-to-date status, so reporting outdated packages in that format is meaningless. pip enforces this at the top of run() before doing any network work.

Solutions

  1. Use a non-freeze format for outdated listing: `pip list --outdated --format columns` or `--format json`.
  2. If you need a machine-readable list of outdated packages, use `pip list --outdated --format json` and post-process.
  3. Remove PIP_LIST_FORMAT from your environment or config if it is set to freeze while you also pass --outdated.

Example fix

# before
pip list --outdated --format freeze
# after
pip list --outdated --format json
Defensive patterns

Strategy: validation

Validate before calling

def safe_pip_list(outdated: bool, fmt: str) -> list[str]:
    if outdated and fmt == 'freeze':
        raise ValueError('freeze format is incompatible with --outdated; use columns or json')
    return ['pip', 'list', *(('--outdated',) if outdated else ()), f'--format={fmt}']

Prevention

When it happens

Trigger: Running `pip list --outdated --format freeze` or `pip freeze --outdated` (pip freeze delegates to the same code). Also reproducible if PIP_LIST_FORMAT=freeze and PIP_OUTDATED are both set in the environment.

Common situations: Trying to generate a requirements.txt of only outdated packages; piping `pip list --outdated` into a freeze-style script; misconfigured CI that sets both options.

Related errors


AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08). Data as JSON: /api/errors/d7af692417dfadec. Report an issue: GitHub.

Appendix: source

Thrown at src/pip/_internal/commands/list.py:180

            release_control=options.release_control,
            format_control=options.format_control,
            prefer_binary=options.prefer_binary,
        )

        return PackageFinder.create(
            link_collector=link_collector,
            selection_prefs=selection_prefs,
            uploaded_prior_to=options.uploaded_prior_to,
        )

    def run(self, options: Values, args: list[str]) -> int:
        cmdoptions.check_release_control_exclusive(options)

        if options.outdated and options.uptodate:
            raise CommandError("Options --outdated and --uptodate cannot be combined.")

        if options.outdated and options.list_format == "freeze":
            raise CommandError(
                "List format 'freeze' cannot be used with the --outdated option."
            )

        cmdoptions.check_list_path_option(options)

        packages: _ProcessedDists = [
            cast("_DistWithLatestInfo", d)
            for d in get_environment(options.path).iter_installed_distributions(
                local_only=options.local,
                user_only=options.user,
                editables_only=options.editable,
                include_editables=options.include_editable,
                skip=set(stdlib_pkgs),
            )
        ]

        # get_not_required must be called firstly in order to find and
        # filter out all dependencies correctly. Otherwise a package

View on GitHub (pinned to f399c37189)