1Panel-dev/1Panel · error · ValueError
symlink-not-allowed
Error message
symlink-not-allowed
What it means
Raised when the joined candidate file (modules_root/<artifact path>) is itself a symlink. The verifier refuses symlinks explicitly before resolve() so a link pointing outside the modules root can never be checksummed, even if its target resolves back inside.
Source
Thrown at scripts/openresty-modules/diagnose-install.sh:220
modules_root = pathlib.Path(sys.argv[2]).resolve()
modules = json.loads(state_path.read_text(encoding="utf-8"))
failed = False
print("module\tbuild_status\ttarget_key\tartifact\texpected\tactual\tresult")
for module in modules:
for build in module.get("builds") or []:
target_key = (build.get("target") or {}).get("key", "")
for artifact in build.get("artifacts") or []:
relative = artifact.get("path", "")
expected = artifact.get("checksum", "")
result = "OK"
actual = ""
try:
pure = pathlib.PurePosixPath(relative)
if not relative or pure.is_absolute() or ".." in pure.parts or "\\" in relative:
raise ValueError("unsafe-path")
candidate = modules_root / pathlib.Path(*pure.parts)
if candidate.is_symlink():
raise ValueError("symlink-not-allowed")
full_path = candidate.resolve(strict=True)
if modules_root not in full_path.parents:
raise ValueError("outside-module-root")
if not full_path.is_file():
raise ValueError("not-regular-file")
digest = hashlib.sha256()
with full_path.open("rb") as handle:
for chunk in iter(lambda: handle.read(1024 * 1024), b""):
digest.update(chunk)
actual = digest.hexdigest()
if actual.lower() != expected.lower():
raise ValueError("checksum-mismatch")
except Exception as error:
result = str(error)
failed = True
print("\t".join([
module.get("name", ""), build.get("status", ""), target_key,
relative, expected, actual, result,View on GitHub (pinned to 5ac7c80881)
Solutions
- Replace the symlink with the real file: rm modules/resty/mod.so && cp /somewhere/else/mod.so modules/resty/mod.so
- Re-verify the checksum of the copied file matches the manifest (sha256sum) or re-run diagnose-install.sh
- Find other links with: find <modules_root> -type l
Example fix
# before ln -s /opt/other/mod.so /opt/1panel/openresty/modules/resty/mod.so # after cp /opt/other/mod.so /opt/1panel/openresty/modules/resty/mod.so
Defensive patterns
Strategy: validation
Validate before calling
find /opt/1panel/openresty/modules -type l -print # must be empty before diagnosing
Prevention
- Install artifacts by copy, never symlink
- After unpacking tarballs, strip links: tar --dereference when creating, find -type l audit after extracting
When it happens
Trigger: diagnose-install.sh verifies a build whose artifact path under the modules root is a symlink (ln -s /somewhere/else/mod.so modules/resty/mod.so), created manually or by an install step that linked instead of copied.
Common situations: Operator 'deduplicated' module files with symlinks; a package install used update-alternatives-style links; artifacts were restored from a tarball that preserved symlinks.
Related errors
- unsafe-path
- outside-module-root
- Unsupported SAML2 navigation protocol
- not-regular-file
- checksum-mismatch
AI-assisted analysis of 1Panel-dev/1Panel@5ac7c80881 (2026-08-15).
Data as JSON: /api/errors/5cef3087fb23e1c9.
Report an issue: GitHub.