Error [The requested command export does not exist.]

The requested command export does not exist. の直し方(Poetry 2 の requires-plugins が黙って登録されない)

FIX SUMMARY verified
Applies when
python@sha256:ffb752e139c0a19692a43af8d8523b274222dd68eebad5d583b45c2201c6e30apoetry 2.1.0〜2.4.1 で確認(2.1.0 が追加した Env.scheme_dict が、書き込めないパスを $HOME/.local へ読み替える。[tool.poetry.requires-plugins] が上書きした purelib と噛み合って入れ先が壊れる。.poetry/plugins へ入れる方式自体は 2.0.0 からあり、2.0.x では動く。上流 issue #10341 と修正 PR #10998 はどちらも open)Poetry が入っている環境の scripts と data(システム Python なら /usr/local/bin と /usr/local)へ、Poetry を実行するユーザーが書けない構成——Dockerfile で root が pip install poetry してから USER を切り替えた形が代表例。install は rc=0 でプラグインを入れたと出力するのに、poetry export だけがコマンド不在で止まる

Verified: reproduced in python@sha256:ffb752e139c0a19692a43af8d8523b274222dd68eebad5d583b45c2201c6e30a, then the The requested command export does not exist. signature was gone after the fix (exit 0).

Poetry を 2 系に上げると、poetry export が無いと言われます。

The requested command export does not exist.

Documentation: https://python-poetry.org/docs/cli/

同じ原因でもう 1 つの文言があります。どちらが出るかは Poetry の版で決まります。

The command "export" does not exist.
Poetrypoetry export(プラグイン無し)
1.8.5動く。poetry-plugin-export will not be installed by default in a future version of Poetry. と警告するだけ
2.0.0 / 2.0.1The command "export" does not exist.
2.1.0 / 2.4.1The requested command export does not exist.

どちらが出るかは poetry --version で決まります。検索して出てくる記事の文言が自分と違っていても、扱っているのは同じ症状です。

Poetry 2.0.0 で export が本体から外れ、poetry-plugin-export というプラグインになりました。 1.8.5 の警告はその予告です。プラグインを入れれば戻ります。

poetry self add poetry-plugin-export

ここまでで直った人は、以下を読む必要はありません。 この記事が扱うのは、プラグインを入れる宣言を pyproject.toml に書いたのに、同じエラーが消えない場合です。

まず、どちらの状態かを分ける

pyproject.toml に次の宣言があるかを見てください。

[tool.poetry.requires-plugins]
poetry-plugin-export = ">=1.8"

これは Poetry 2.x のドキュメントが案内している書き方で、poetry install の時点でプラグインを取りに行きます。この宣言があって、しかも poetry export が上のエラーで止まるなら、この記事の症状です。

poetry install は終了コード 0 で終わり、プラグインを入れたと出力します。

$ poetry install --no-root
Ensuring that the Poetry plugins required by the project are available...
The following Poetry plugins are required by the project but are not installed in Poetry's environment:
  - poetry-plugin-export (>=1.8)
Installing Poetry plugins only for the current project...
  - Installing poetry-plugin-export (1.10.0)

Writing lock file

エラーも警告も出ません。次に poetry export を叩いた時点で初めて、入っていないことが分かります。

直し方の要点を先に

ビルドの段階で、Poetry を実行するのと同じ経路にプラグインを入れます。 Dockerfile なら 1 行です。

RUN pip install poetry==2.4.1 \
 && poetry self add poetry-plugin-export
USER app

pip install poetry-plugin-export でも同じ結果になります(Poetry と同じ Python に入れる場合)。どちらも、USER を切り替えたあとの poetry export が終了コード 0 になります。

RUN pip install poetry==2.4.1 poetry-plugin-export
USER app

pyproject.toml の requires-plugins は消さなくて構いません。ただし、この 2 つはその宣言を働かせているのではなく、別経路でプラグインを入れて結果を合わせています。 宣言のほうを働かせたい場合は次の節です。

宣言をそのまま働かせる場合

requires-plugins の宣言を版の正本として使い続けるなら、Poetry を仮想環境に入れて、その仮想環境ごと実行ユーザーへ渡します。 下はイメージの中で自分が作った仮想環境に対する操作です。ホストに入れた Poetry へ chown を打たないでください(共有マシンなら他のユーザーの実行環境の所有者を書き換えます)。ホストで宣言を働かせたいなら、最初からそのユーザーで仮想環境を作ります。

RUN python -m venv /opt/poetry-venv \
 && /opt/poetry-venv/bin/pip install poetry==2.4.1 \
 && chown -R app /opt/poetry-venv
ENV PATH="/opt/poetry-venv/bin:$PATH"
USER app

所有者を渡すのが一番手っ取り早い形です。仮想環境に入れただけでは直りません——root が作った仮想環境を別のユーザーが実行すると、システムの Python に入れた場合と同じく poetry export が終了コード 1 になります(次節の表)。

イメージを変えられない場合

USER が固定された CI ランナーや、配布された共有ベースイメージのように、ビルド段に手を入れられない場合は、実行時の環境変数 1 つで通ります。

ENV PYTHONNOUSERSITE=1

docker run -e PYTHONNOUSERSITE=1 ... でも同じです。効かせる相手は poetry install を走らせる側で、これを立てると宣言どおり .poetry/plugins にプラグインが入ります。理由は後述——Poetry の退避先がユーザーサイトなので、それを止めると退避そのものが起きません。 ユーザーサイトを止めるので、pip install --user で入れたものに依存している構成では影響を確認してください。

なぜ Poetry 2.1.0 で変わったのか

同じ pyproject.toml・同じ手順で、Poetry の版だけを変えた結果です。実行ユーザーは root 以外に固定しています。

Poetrypoetry install のログpoetry export
2.0.0Installing poetry-plugin-export (1.9.0)通る
2.0.1同上通る
2.1.0Installing poetry-plugin-export (1.10.0)失敗
2.1.2同上失敗
2.4.1同上失敗

境界は 2.0.1 と 2.1.0 のあいだです。 PyPI にこの 2 つの中間のリリースは無いので、境界はここで確定します。2.1.0〜2.4.1 のあいだで測ったのは 2.1.0 / 2.1.2 / 2.4.1 の 3 点で、2.4.1 は執筆時点の最新版です。

変わったのは requires-plugins の側ではありません。 プラグインをプロジェクト配下の .poetry/plugins へ入れる方式も、そのために purelib を上書きする実装も、2.0.0 の時点で既にあります(2.0.0 の plugin_manager.py に PATH = Path(".poetry") / "plugins" と poetry_env.paths["purelib"] = str(self._path) があります)。それでも 2.0.x は通ります。

2.1.0 が足したのは Env.scheme_dict です。CHANGELOG にはこう書かれています。

Fix an issue where installation failed with a permission error when using the system
environment as a user without write access to system site packages (#9014).

システムの site-packages に書けないユーザーを救済する処理で、書けないパスを $HOME/.local の下へ読み替えます。この読み替えが、requires-plugins が上書き済みの purelib と噛み合いません。

なぜ書き込み権限で決まるのか

Env.scheme_dict は、インストール先の各パス(purelib / platlib / headers / scripts / data)を順に見て、1 つでも書けなければ全部を $HOME/.local の下へ退避します。判定は所有者ではなく、そのディレクトリに一時ファイルを作れるかどうかです。

ここで効いてくるのが、requires-plugins による上書きです。purelib と platlib は既に .poetry/plugins(プロジェクト配下)へ差し替わっているので、最初から書けます。残るのは scripts(/usr/local/bin)と data(/usr/local)で、判定を決めているのはこの 2 つだけです。

Poetry の置き場所実行ユーザー.poetry/plugins に実体poetry export
システムの Python(pip install poetry)rootある通る
システムの Python別ユーザー無い失敗
システムの Python + chmod a+w /usr/local /usr/local/bin別ユーザーある通る
仮想環境(root が所有)別ユーザー無い失敗
仮想環境 + chmod a+w(所有者は root のまま)別ユーザーある通る
仮想環境(実行ユーザーへ chown)別ユーザーある通る

site-packages の書き込み可否は関係しません。 上の 3 行目は site-packages を root 所有の 755 のまま触っていません。requires-plugins の入れ先は既に .poetry/plugins へ差し替わっているので、site-packages はこの判定に使われないからです。chmod -R a+w を site-packages に当てても、エラーは 1 文字も変わりません。

Dockerfile で pip install poetry してから USER を切り替える形は、この表の 2 行目にそのまま当たります。コンテナだけの話ではありません——sudo pip install poetry した開発機で自分のユーザーとして poetry install を打つ構成も同じ条件です(上流 issue にも macOS からの報告があります)。

入ったはずのプラグインはどこにあるか

失敗した側の .poetry/plugins には、設定とロックファイルしか残りません。

$ find .poetry
.poetry
.poetry/plugins
.poetry/plugins/config.toml
.poetry/plugins/poetry.lock
.poetry/.gitignore

実体はホームの下にあります。$HOME/.local がパス成分ごとに前置された名前のディレクトリが生えます。

$ ls -a $HOME
.bash_logout  .bashrc  .cache  .localhome  .localusr  .profile  p

$ ls "$HOME/.localhome/home/app/.localapp/home/app/.localp/home/app/.local.poetry/home/app/.localplugins/poetry_plugin_export"
__init__.py  command.py  exporter.py  plugins.py

ls -a でホームに .local で始まる見慣れないディレクトリが並んでいたら、この症状です。

この名前は、退避先を組み立てる 1 行から出ています。 Env.scheme_dict は、退避するときの接頭辞を「scripts と purelib の共通パス」として求めます。ところが purelib は requires-plugins によって .poetry/plugins(プロジェクト配下)へ差し替わっているので、/usr/local/bin との共通パスは / にしかなりません。その後の置換が文字列置換なので、パス区切りの / が全部 $HOME/.local に置き換わります。

自分の環境で 1 回で確かめられます。

$ python -c '
from poetry.utils.env import EnvManager
e = EnvManager.get_system_env(naive=True)
e.set_paths(purelib="/work/.poetry/plugins", platlib="/work/.poetry/plugins")
print(e.scheme_dict["purelib"])'
/home/app/.localwork/home/app/.local.poetry/home/app/.localplugins

仮想環境でも条件は変わりません。 Poetry がプラグイン導入時に使う環境は EnvManager.get_system_env(naive=True) で作られ、これは仮想環境の中で動かしても is_venv() が False になります。退避するかどうかの判定に使われるのも site.ENABLE_USER_SITE ではなく site.check_enableusersite() で、こちらは仮想環境でも True を返します(python -c 'import site; print(site.ENABLE_USER_SITE, site.check_enableusersite())' で False True と出ます)。引き金は 1 つで、確かめる場所は上の 2 パスだけです。

上流の issue(python-poetry/poetry#10341)は open で、修正 PR(#10998「Fix installation of project plugins if Poetry’s environment is not writable」)も 2026-07-30 から open のままです。これがリリースに入れば、この症状はその版から消えます。

切り分け

  • requires-plugins を書いていない → この記事の症状ではありません。poetry self add poetry-plugin-export で入ります。Poetry を pipx で入れているなら、Poetry のドキュメントは pipx inject poetry poetry-plugin-export を案内しています(この経路は実測していません)。
  • poetry install は成功しているのに poetry export だけ落ちる → この記事の症状です。まず ls -a $HOME を見てください。
  • 手元では通るのに CI・コンテナだけ落ちる → Dockerfile に USER があるかを見てください。ビルド段で pip install poetry し、実行段で別ユーザーに切り替えている構成が該当します。sudo pip install poetry した開発機でも同じ条件になります。
  • poetry self show plugins の出力で判定したい → 成功している側では poetry-plugin-export (1.10.0) … 1 application plugin が出ます(chmod で通した構成で実測)。ただし失敗側でも空とは限らないので、確実なのは .poetry/plugins の中身を見ることです。
  • The command "export" does not exist. のほうが出ている → Poetry 2.0.0 / 2.0.1 の文言です(2.1.0 で The requested command export does not exist. に変わりました)。症状は同じ「コマンドが無い」ですが、原因は別です——2.0.x はプラグインを入れていないだけで、requires-plugins を書けば動きます(2.0.1 で実測)。この記事の後半は当たりません。
  • export 以外のコマンドが無いと言われる → 2.0.0 で分離されたのは export だけではありません。同じ形で poetry self add するか、この記事の構成の問題を疑ってください(本記事が実測したのは export だけです)。

検証環境

  • image: python:3.13-slim(digest 固定 sha256:ffb752e1...)、ネットワーク有り(PyPI から取得するため)
  • 再現:[tool.poetry.requires-plugins] を書いた pyproject.toml を、root が作った仮想環境の Poetry 2.4.1 で、別ユーザーから poetry install --no-root → 成功。続けて poetry export --format requirements.txt → The requested command export does not exist. で終了コード 1
  • 修正:同じ Poetry・同じ pyproject.toml のまま、仮想環境を実行ユーザーへ chown → 同じ 2 コマンドが終了コード 0 になり、idna==3.10 が出力される

再現から修正までは errfix の検証ハーネスが機械的に確認しています。reproduce と fix の差は chown の 1 行だけで、pyproject.toml は 2 つのディレクトリで byte 単位に同一です。

版の表(2.0.0 / 2.0.1 / 2.1.0 / 2.1.2 / 2.4.1)、文言の表(1.8.5 の警告と、2.0.x と 2.1.0 以降で変わるエラー文)、置き場所と権限の表、site-packages を書き込み可にしても変わらないこと、chmod a+w /usr/local /usr/local/bin の 2 つだけで通ること(site-packages は root 所有 755 のまま)、仮想環境を chown せず chmod だけで通ること、PYTHONNOUSERSITE=1 で通ること、poetry self add と pip install poetry-plugin-export をビルド段で打てば別ユーザーでも通ること、poetry self show plugins が成功側でプラグインを表示すること、失敗時の .poetry/plugins の中身と $HOME に生えるディレクトリ名は、いずれも同じイメージで実測しています。候補ごとにコンテナを分けて測っています——同じコンテナで続けて測ると、前の手当てが次の測定を通してしまいます。

上に貼った $HOME の中身と長いパスは、プロジェクトを /home/app/p に置いて測ったときの出力です(検証ケースは /work に置いているので、.localwork のような名前になります)。

requires-plugins がプロジェクト配下へ入れる仕様と purelib を上書きする実装、退避先を組み立てる Env.scheme_dict は、Poetry 2.4.1 と 2.0.0 の両方の site-packages を直接読んで比べました。2.1.0 の CHANGELOG と PR #9014、issue #10341、PR #10998 は GitHub で確認しています。

pipx で入れた Poetry、Poetry 公式インストーラで入れた Poetry、export 以外の分離コマンド、Windows は実測していません。 ただし pipx と公式インストーラはどちらも Poetry を実行ユーザーの所有物として置くので、上の条件からは外れると考えられます(測ってはいません)。

検証(machine-verified)

この修正は python@sha256:ffb752e139c0a19692a43af8d8523b274222dd68eebad5d583b45c2201c6e30a のバージョン固定コンテナ内で再現し、修正後に The requested command export does not exist. のシグネチャが消えることを機械で確認しています。

verify — run-case.mjs
$ node run-case.mjs python/poetry2-export-command-not-exist
● reproduce The requested command export does not exist. present ✓
● apply fix exit 0
● re-run The requested command export does not exist. gone ✓
PASS verified · python@sha256:ffb752e139c0a19692a43af8d8523b274222dd68eebad5d583b45c2201c6e30a · signature gone

確認したのは上のイメージの中だけです。別の環境で直らなかった、記述が違う、という場合は 報告してください(対象と検証イメージは件名・本文に入ります)。