Error codes
Error codes are stable strings. Match on the code, not on the message text.
| Where you see it | Form |
|---|---|
| CLI text output | [CODE] message on stderr. The exit code is 1. |
CLI --json | {"ok":false,"code":"CODE","message":"…","hint":"…"} on stdout. Some failures add a data field with a report. |
| App RPC (the UI calling the backend) | {"success":false,"error":{"code":"…","message":"…"}} with HTTP status 200. In the browser, ctx.call rejects with {code, message}. See the App API reference. |
When check finds a problem in a project, the error message includes the file, line and a suggestion. The code is the first error.
CLI errors
Section titled “CLI errors”The table lists every code the synopkgland command can report. Codes that start with COMPOSE_, CONTRACT_, INSTALL_ and HOMES_ belong to container (Compose) apps. Codes that start with STANDALONE_ belong to native apps (dsm-package.yaml).
| Code | Meaning | What to do |
|---|---|---|
ADD_FILE_CONFLICT | add found an existing file that differs from the file the capability would write. | Move or merge the listed files, then run add again. add never overwrites different content. |
ADD_LAYOUT_UNSUPPORTED | The capability needs the standard backend folder. | Set backend.dir: backend in dsm-package.yaml, or merge the capability files by hand. |
APP_SCRIPT_INVALID | A dsm-scripts/<DSM script name> entry is a symlink, directory or special file. | Make it a regular file in the project’s dsm-scripts/ folder. |
APP_SCRIPT_NOT_EXECUTABLE | A dsm-scripts/<DSM script name> file is not executable; DSM runs it directly. | Run chmod +x on the file. |
APP_SCRIPT_NO_SHEBANG | A dsm-scripts/<DSM script name> file does not start with #!. | Start the file with an interpreter line such as #!/bin/sh. |
APP_SCRIPT_UNKNOWN | A file in the project’s dsm-scripts/ folder does not have a DSM package script name the SDK runs. | Name it preinst, postinst, preuninst, postuninst, preupgrade, postupgrade or start-stop-status, or move it out of dsm-scripts/. prereplace and postreplace are not supported. |
BUILD_NOT_REPRODUCIBLE | build --verify-reproducible built an SPK whose bytes differ from the first build. | Read the listed payload and metadata files, remove what changes between builds (timestamps, random or absolute paths, unpinned dependencies), and build again. |
BUILD_SPK_FAILED | Packaging the SPK failed during deploy. | Run synopkgland check, fix the errors, check file permissions in the project, and retry. |
CAPABILITY_COMBINATION_INVALID | The capabilities do not work together, or do not work with your UI or daemon. | login and delegate need --ui vue. A daemon cannot be combined with jobs unless delegate.lifetime is until-revoked. |
CAPABILITY_INVALID | A capability name or value is not valid. | Use files: session, jobs: true (or {worker: sha256-v1}), identity: standalone, rootOps: true, or a valid delegate block. |
CAPABILITY_UNSUPPORTED | The project type does not support capabilities. | Capabilities need a native Go project (init -t native-go). Container (Compose) and binary projects do not support them. |
CATALOG_INSTALL_FAILED | Removing or installing a package through DSM Package Center failed. | Read the message, check the install log in Package Center on the NAS, or retry by hand. |
CLI_ARCH_INVALID | The --arch value is not valid. | Use x86_64, aarch64 or armv7. armv7 is for native-go and binary, not Container Manager apps. |
CLI_ARGUMENT_MISSING | A required argument is missing. | Run the command with --help to see its arguments. |
CLI_COMMAND_UNKNOWN | The command does not exist. | Run synopkgland --help to list commands. |
CLI_JOBS_INVALID | The --jobs value is not a positive integer. | Use --jobs 1 (the default) or a larger whole number. |
CLI_OPTION_ARGUMENT_MISSING | An option needs a value and has none. | Add the value after the option. |
CLI_OPTION_INVALID | An option value is not valid, or the option does not apply to this command. | Run the command with --help. For --param, --share and --run-as, write NAME=value. --project does not apply to init. |
CLI_OPTION_MISSING | A required option is missing. | Run the command with --help to see the required options. |
CLI_OPTION_UNKNOWN | The option does not exist. | Run the command with --help to list its options. |
CLI_OUTPUT_ARCH_REQUIRED | Writing one file with -o needs exactly one architecture. | Pass a single --arch with -o, or use --out-dir. |
COMMAND_FAILED | The command failed and no more specific code applies. | Read the message and stderr, fix the cause, and retry. |
COMPOSE_BIND_SOURCE_FORBIDDEN | A volume mount uses a host path that is not allowed. | Mount ${SYNOPKG_PKGVAR}, ${SYNO_APP_SECRETS_DIR} or a ${SLOT} you declared as a shared_folder install parameter. |
COMPOSE_BIND_SOURCE_UNDECLARED | A volume mount uses a Shared Folder variable that is not declared. | Declare the shared_folder parameter under install in synology-app.yaml. |
COMPOSE_BIND_SUFFIX_INVALID | The sub-path after a Shared Folder variable is not valid. It contains .. or control characters. | Use a plain relative sub-path, for example ${MEDIA_SHARE}/data:/data. |
COMPOSE_BUILD_FORBIDDEN | compose.yaml uses build:. The NAS only runs existing images. | Remove build: and use an image, preferably pinned by digest (image@sha256:…). Run check again. |
COMPOSE_CAP_ADD_FORBIDDEN | A service uses cap_add and privilege.cap_add is not declared. | Set privilege.cap_add: true in synology-app.yaml, or remove cap_add. |
COMPOSE_DEVICES_FORBIDDEN | A service uses devices and privilege.devices is not declared. | Set privilege.devices: true in synology-app.yaml, or remove devices. |
COMPOSE_DYNAMIC_ROUTE_UNSUPPORTED | compose.yaml uses a variable form that is not supported, or a secret or config source that DSM does not load. | Use only ${NAME} substitution with string or boolean install answers. Remove secrets and configs. |
COMPOSE_ENV_MISSING | synopkgland test could not find the folders it creates for a Compose app (SYNOPKG_PKGVAR and the secrets folder). | Check that the test run can create the folders, then run test again. |
COMPOSE_GATEWAY_PORT_EXPOSED | The DSM sign-in gateway must be the only way in, but the published port for adminport listens on every network interface. | Bind the port to loopback, for example "127.0.0.1:18333:18333", or set integration.web.access: public. |
COMPOSE_HOST_BIND_FORBIDDEN | A volume mount hard-codes a host path such as /volume1/… or ./. | Declare a shared_folder install parameter and mount it as ${SLOT}. |
COMPOSE_HOST_IPC_FORBIDDEN | A service uses ipc: host and privilege.host_ipc is not declared. | Set privilege.host_ipc: true, or remove ipc: host. |
COMPOSE_HOST_NETWORK_FORBIDDEN | A service uses host networking and privilege.host_network is not declared. | Set privilege.host_network: true, or use a normal Compose network. |
COMPOSE_HOST_PID_FORBIDDEN | A service uses pid: host and privilege.host_pid is not declared. | Set privilege.host_pid: true, or remove pid: host. |
COMPOSE_MISSING | check found neither compose.yaml nor dsm-package.yaml. | Run the command in the project root, or create one of the two files. |
COMPOSE_NAMED_VOLUME_UNDECLARED | A service uses a named volume that is not declared in the top-level volumes. | Add the volume to the top-level volumes of compose.yaml, or mount a managed folder instead. |
COMPOSE_NOT_HEALTHY | During synopkgland test, a service did not become healthy in time. | Check the healthcheck and the app log. |
COMPOSE_NOT_RUNNING | During synopkgland test, a service did not stay running. | Check the container start command and its log to find why it exits. |
COMPOSE_NUMERIC_COMMAND_ARG_FORBIDDEN | A command or entrypoint list has an item that is only digits. DSM can turn it into a number and the project then fails to start. | Put the whole command in one string, for example command: ["sh", "-c", "httpd -f -p 8080 -h /srv"], or join the flag and value as "-p8080". |
COMPOSE_POSIX_ALL_SHARES_SUFFIX_FORBIDDEN | A posix_all_shares value has a sub-path added. | Use the whole ${ALL_SHARES} source and nothing after it. |
COMPOSE_POSIX_ALL_SHARES_UNDECLARED | compose.yaml uses the all-shares variable but no install parameter has type: posix_all_shares. | Declare an install parameter with type: posix_all_shares. |
COMPOSE_PRIVILEGED_FORBIDDEN | A service uses privileged: true and privilege.privileged is not declared. | Set privilege.privileged: true, or remove privileged: true. |
COMPOSE_ROUTE_UNSUPPORTED | The project uses a Compose feature that DSM cannot run. | Use a prebuilt image and supported install parameters. Remove unsupported privileges, secrets or build. |
COMPOSE_SERVICE_NOT_FOUND | depends_on names a service that compose.yaml does not define. | Fix depends_on to name a defined service. |
COMPOSE_SOCKET_MOUNT_FORBIDDEN | A service mounts the Docker socket or another sensitive system socket. | Remove the docker.sock mount. Use a shared_folder or the app’s own file API to reach files. |
COMPOSE_USER_CONFLICTS_DSM_USER | A service sets user and the app also declares a dsm_user install parameter. | Remove user from compose.yaml. The dsm_user parameter sets ${NAME_UID}:${NAME_GID} and group_add for you. |
COMPOSE_USER_NUMERIC_FORBIDDEN | A service hard-codes a numeric uid:gid. | Declare a dsm_user install parameter and use ${NAME_UID}:${NAME_GID}. |
COMPOSE_USER_ROOT_FORBIDDEN | A container runs as root (0:0). | Declare a dsm_user install parameter and use ${USER_UID}:${USER_GID}. |
CONTAINER_ARCH_UNSUPPORTED | Container apps support only x86_64 and aarch64. DSM has no Container Manager for armv7. | Use --arch x86_64 or --arch aarch64, or build a native Go app. |
CONTRACT_ACCESS_GROUPS_INVALID | integration.web.groups is missing, malformed, or used without access: dsm-groups. | Use access: dsm-groups with a list of DSM group names, or remove groups. |
CONTRACT_ACCESS_INVALID | integration.web.access has an unknown value. | Use dsm-users (default), dsm-admins, dsm-groups (with groups), or public. |
CONTRACT_ACCESS_REQUIRES_WEB | integration.web.access or groups is set on an app with no web page. | Remove them, or add an adminport that matches a published Compose port. |
CONTRACT_ADMINPORT_INVALID | adminport is not an integer. | Set adminport to an integer that matches a published Compose port. |
CONTRACT_ADMINPORT_UNMAPPED | adminport does not match any published port in compose.yaml. | Add a port mapping for it under ports, for example "8080:80". |
CONTRACT_DSM_USER_DUPLICATE | The app declares more than one dsm_user install parameter. | Keep only one. |
CONTRACT_HOMES_PATH_FORBIDDEN | A homes install parameter has a path or default value. | Declare only type: homes and reference the parameter in Compose. The package resolves the path at install time. |
CONTRACT_HOMES_UNSUPPORTED | The homes install parameter type is not supported. check reports a warning and deploy refuses it. | Use type: shared_folder for a folder the administrator picks. |
CONTRACT_I18N_INVALID | The i18n block in synology-app.yaml is not valid. | Use only i18n.info, keyed by a supported locale such as zh-TW or ja, with one-line displayname / description without " or \. Write English at the top level. |
CONTRACT_ICON_INVALID | The icon in synology-app.yaml is not a usable package icon. | Point icon at a square PNG of at least 256×256 inside the project, or an icon_<size>.png directory with icon_256.png. Remove it to use the SDK default icon. |
CONTRACT_INVALID_STRING | A string in synology-app.yaml has control characters or a ${…} substitution that is not allowed. | Remove control characters and ${. Declare install parameters under install. |
CONTRACT_LAUNCH_INVALID | integration.web.launch has an unknown value. | Use dsm-window (default) or new-page. Leave it out for an app with no web page. |
CONTRACT_LAUNCH_REQUIRES_WEB | integration.web.launch is set on an app with no web page. | Remove it, or add an adminport that matches a published Compose port. |
CONTRACT_MISSING_FIELD | synology-app.yaml is missing a required field. | Add the field the message names, for example package, version or displayname. |
CONTRACT_PACKAGE_TOO_LONG | The package name is longer than 32 characters, the DSM limit. | Shorten package to 32 characters or fewer. |
CONTRACT_PORTAL_REQUIRES_EXECUTOR | A Compose app declares integration.web.portal. A Compose app has no executor, and only root can stop DSM’s web server from serving a Login Portal alias after uninstall. | Remove integration.web.portal. If you need an alias, an administrator sets up a reverse proxy in DSM. |
CONTRACT_POSIX_ALL_SHARES_LISTING_UNSUPPORTED | posix_all_shares needs the CLI to read the NAS Shared Folder list at install time. Package Center and Package Source listings cannot do that. | Install with synopkgland deploy --host <name>. Do not list this app in a Package Source. |
CONTRACT_POSIX_ALL_SHARES_VALUE_FORBIDDEN | A posix_all_shares parameter has a default or a path. | Declare only type: posix_all_shares. |
CONTRACT_SCHEMA_INVALID | synology-app.yaml does not match the schema. | Fix the fields the message names. See Compose manifest reference. |
CONTRACT_SCHEMA_UNSUPPORTED | The schema value in synology-app.yaml is not supported. | Set schema: 1. |
CONTRACT_SECRET_UNSUPPORTED | The secret install parameter type is not supported. check reports a warning and deploy refuses it. | Use type: string for a value that is not sensitive. For a secret, let the app fetch it at start, or put it in a file in ${SYNO_APP_SECRETS_DIR}. |
DEPLOY_ARCH_UNDETERMINED | deploy could not tell the NAS architecture. | Pass --arch x86_64, aarch64 or armv7. |
DEPLOY_BUILD_OUTPUT_INVALID | The build did not produce exactly one SPK for deploy. | Pass a single --arch and run deploy again. |
DEPLOY_FAILED | deploy failed and no more specific code applies. | Check the network connection to the NAS and run synopkgland logs --host <nas>. |
DEPLOY_PARAM_TYPE_INVALID | A --param value does not match the declared type. | Pass a non-empty string for string parameters. Pass only true or false for boolean parameters. |
DEPLOY_PARAM_REQUIRED | The first install of an install-selected delegate has no scope, so its preinst would refuse the install. | Add --param delegate_share=<Shared Folder> or --param delegate_home=true. |
DEPLOY_PARAM_UNDECLARED | --param names an install parameter that is not declared, or a native-go or binary package has no such install wizard value. | For Compose, pass only the string or boolean names declared under install in synology-app.yaml. For native-go and binary, pass only delegate_share or delegate_home of an install-selected delegate. |
DEPLOY_PLAN_INVALID | The deploy plan does not match the project type. | Run check and deploy again. |
DEPLOY_POSIX_ALL_SHARES_LOOKUP_FAILED | deploy could not list the Shared Folders on the NAS with the administrator session. | Check that the administrator can list Shared Folders in DSM, or pass the list with --param NAME=…. |
DEPLOY_VERSION_INVALID | The package version is not valid, is lower than the installed version (“Refusing downgrade”), or has the same version without a higher build. | Set a higher valid version or build, then deploy. |
DEVELOPMENT_INSTANCE_UNSUPPORTED | A native Go app does not support --dev. | Run init with a different package name to get a separate development app. |
DSM_COMPOUND_FAILED | A step of a DSM install request failed. | Read the api, method and errorCode in the response and the Package Center log on the NAS, then retry. |
DSM_DEPENDENCY_CONFLICT | DSM refused the request because a running package depends on this one. | Stop the packages that DSM lists, then retry the upgrade. |
DSM_TLS_UNTRUSTED | The DSM certificate is self-signed, expired or for another name, and this computer does not trust it. | Export the NAS certificate or its CA as PEM and run with NODE_EXTRA_CA_CERTS=<that file>, or give DSM a trusted certificate that matches the host profile. Do not turn certificate checks off. |
DSM_REQUEST_FAILED | A request to DSM failed. | Check the DSM session, the request parameters and the Package Center log, then retry. |
DSM_USER_LOGICAL_NAME_REQUIRED | A dsm_user value is a number. It must be a DSM user name. | Pass a user name, for example --run-as RUN_AS=alice. |
DSM_USER_REQUIRED | The app has a Shared Folder but no dsm_user install parameter. | Add exactly one install.<NAME>.type: dsm_user and use ${NAME_UID}:${NAME_GID} in Compose. |
EXECUTOR_BUILD_FAILED | Building the helper that runs administrator operations (for rootOps and delegate) failed. | Read the compiler output in the message and fix it. Native apps need Go 1.21 or later; the build uses exactly Go 1.26.9 and fails when it cannot get it (offline) or when a binary names another Go release. |
EXECUTOR_DIGEST | A digest the build gave the administrator-operations helper is not a 64-character SHA-256 hex string. | Rebuild with synopkgland build. Do not call the assembler with your own digests. |
EXECUTOR_DIGEST_MISMATCH | The executor built from the SDK version in backend/go.mod does not match the SHA-256 table in the CLI, or the table has no entry for that SDK version. | Require a released SDK version and build with Go 1.26.9. If the version is newer than the CLI, update the CLI. |
EXECUTOR_DIGEST_UNVERIFIED | Warning: SYNOPKGLAND_SDK_DIR points at a local SDK, so the executor was not checked against the SHA-256 table. | Use it only for development. Unset SYNOPKGLAND_SDK_DIR and build again before you ship the SPK. |
SDK_REQUIRED | rootOps or delegate needs the SDK, but backend/go.mod does not require github.com/synopackageland/syno-pkg-land-sdk. | Require the SDK at the CLI’s minor version in backend/go.mod, or use the Go backend that init creates. |
SDK_TAG_REQUIRED | The Rust App’s Cargo.lock does not pin exactly one syno-pkg-land-app to a release tag (branch, rev, path, registry and multiple versions are rejected). | Write syno-pkg-land-app = { git = "https://github.com/synopackageland/syno-pkg-land-sdk", tag = "vX.Y.Z" } in Cargo.toml, run cargo update -p syno-pkg-land-app and commit Cargo.lock. |
SDK_VERSION_MISMATCH | @synopackageland/sdk in frontend/package.json is not the SDK version that backend/go.mod requires. | Use the same version in both. For a file: dependency, the version in that folder’s package.json counts. |
SDK_UNSUPPORTED | The SDK the backend requires (backend/go.mod or backend/Cargo.lock) is not on this CLI’s minor version line. | Use a CLI with the same minor version as the SDK, or move the SDK to a version the message lists. |
SDK_DIR_NOT_READY | SYNOPKGLAND_SDK_DIR points at a folder without go/go.mod, or a Vue project needs the SDK’s ts package and it is not built (no ts/dist). | Point it at a syno-pkg-land-sdk checkout. For a Vue project, run npm ci && npm run build in $SYNOPKGLAND_SDK_DIR/ts first. |
SDK_DOWNLOAD_FAILED | go mod download could not fetch the SDK version that backend/go.mod requires. | The CLI fetches the private SDK with git. Give git a credential for github.com; verify access with git ls-remote https://github.com/synopackageland/syno-pkg-land-sdk. Then check that the version exists. Offline, run go mod download once on the same machine while online. |
STANDALONE_LOGIN_STYLE_IMAGE_INVALID | An image that login_style names is missing, in the wrong format or the wrong size. | Use a JPEG wallpaper of at least 1920×1080 and at most 2 MiB, a 320×200 JPEG wallpaper_thumbnail and a 680×124 PNG title, inside the project. |
STANDALONE_LOGIN_STYLE_INVALID | login_style in dsm-package.yaml is malformed, or set without portal. | Declare portal, and give login_style only color (#RRGGBB), wallpaper together with wallpaper_thumbnail, and title. Omit login_style to use the CLI default style. See Manifest reference. |
STANDALONE_PYTHON_SDK_MISSING | The App’s SDK version has no Python SDK (python/synopkgland_app). | Point SYNOPKGLAND_SDK_DIR at a syno-pkg-land-sdk checkout that has python/synopkgland_app, or require an SDK release that ships it. |
STANDALONE_REQUEST_TIMEOUT_SHORT | The request deadline ends before a root program that root.run may run would answer. The executor answers 10 seconds after run.timeout_s, and its client waits 10 more. | Set backend.timeout_seconds to at least the program’s run.timeout_s (20 by default) + 20, or lower run.timeout_s. |
TEMPLATES_MISSING | @synopackageland/templates is not installed. | Reinstall @synopackageland/cli, or point SYNOPKGLAND_TEMPLATES_DIR at a templates checkout. |
EXECUTOR_PACKAGE | The package name is not valid for the administrator-operations helper. | Use a package name that starts with a letter and has 2 to 64 letters and digits. |
EXECUTOR_PIN_REQUIRED | The package uses rootOps or delegate but the build has no helper attached. | Build with synopkgland build so the helper is included. |
EXECUTOR_POLICY | The delegate operations or scope are not valid. | Fix capabilities.delegate. See Manifest reference. |
EXECUTOR_POLICY_REJECTED | The executor of the App’s SDK version refuses the policy the CLI generated, so the NAS would refuse it at approval. | The reason names the refused part: root, stop or purge → root.programs, root.stop, uninstall.purge; scope, operation, destination, move or lifetime → capabilities.delegate; portal → portal; entry → entry. Fix that part of dsm-package.yaml. See Manifest reference. |
EXECUTOR_ROOT_PROGRAMS_UNSUPPORTED | The root settings in dsm-package.yaml need an executor with root program settings, which the App’s SDK version lacks. | Use an SDK with root programs, or remove the root settings. |
EXECUTOR_TASK_LENGTH | A scheduled task script for the administrator-operations helper is longer than DSM allows. | Rebuild with synopkgland build. If it persists, shorten the package name. |
EXECUTOR_TASK_PERCENT | A scheduled task script contains a % character, which DSM does not accept. | Rebuild with synopkgland build. If it persists, check the package name and scope for %. |
GATEWAY_ARCH_FAMILY_REQUIRED | The DSM sign-in gateway is a native program, so the SPK needs a target architecture. | Add --arch x86_64 or --arch aarch64. deploy reads it from the NAS. Use integration.web.access: public only for apps that need no DSM sign-in. |
GATEWAY_BUILD_FAILED | Building the DSM sign-in gateway failed, or the result is not a static program for the target architecture. | Read the go build output. The gateway builds with exactly Go 1.26.9; offline, install go1.26.9 or allow GOPROXY to serve golang.org/toolchain. |
GATEWAY_GO_MISSING | Building the DSM sign-in gateway needs Go, and the go command is not found. | Install Go 1.21 or later from https://go.dev/dl/ (the build then uses Go 1.26.9), or set integration.web.access: public. |
HOMES_NOT_ENABLED | The NAS does not have the User Home service on, or DSM did not return the home path. | Turn on User Home in DSM, then deploy again. |
HOST_REQUIRED | No NAS is selected. | Pass --host <profile>. For a local check without a NAS, use deploy --dry-run. |
IMAGE_PIN_REQUIRED | An image is not pinned by digest. | Run synopkgland images pin. |
INIT_BINARY_BUILD_FAILED | Building the example program for the binary template failed. | Install Go and run init again, or supply your own static CGI program. |
INIT_COMPOSE_INVALID | The Compose file given with --from is not valid. | Point --from at a YAML file that has services. |
INIT_DISPLAY_NAME_INVALID | The display name is not valid. | Use one line of text with no " and no \. |
INIT_OPTIONS_UNSUPPORTED | An option does not apply to this template. | --from works only with -t compose. --ui works only with -t native-go. |
INIT_PACKAGE_INVALID | The package name is not valid. | Start with a letter. Use 2 to 64 letters and digits, for example PhotoTagger. |
INIT_SHARED_FOLDER_INVALID | The Shared Folder option is not valid. | Use select or create. With create, also pass --shared-folder-name. --shared-folder works only with -t native-go. |
INIT_TARGET_NOT_EMPTY | The target folder has files that init would overwrite. | Use an empty folder. To add a capability to an existing project, use add. |
INIT_TEMPLATE_REQUIRED | No template is given. | Use -t native-go, binary or compose. |
INIT_TEMPLATE_UNKNOWN | The template name is not known. | Use -t native-go, binary or compose. |
INIT_UI_INVALID | The --ui value is not valid. | Use --ui vue or --ui plain. |
INSTALL_PARAMETER_UNREFERENCED | An install parameter is declared but compose.yaml never uses it. | Use it in compose.yaml as ${NAME}, or remove it from synology-app.yaml. |
INSTALL_STRING_INVALID | An install parameter default has control characters or a ${…} substitution. | Remove them from the default value. |
INSTALL_STRING_TOO_LONG | An install parameter default is longer than 256 characters. | Shorten the default value. |
LOCAL_SPK_INSTALL_FAILED | DSM could not install the SPK that deploy uploaded. | Read the install error in Package Center on the NAS. Check the package version and its requirements. |
MIN_DSM_CONTAINER_FLOOR | The minimum DSM version of a container app is too low. | Container apps need DSM 7.2.1-69057 or later. |
MIN_DSM_INVALID | The minimum DSM version is not valid, or is too low for the capability. | Give a 7.x release or a full 7.x-build version. rootOps needs DSM 7.1-42661 or later. |
NAS_CREDENTIALS_MISSING | No NAS credentials are found. | Set up a synoagentcli profile, or set DSM_URL and DSM_PASSWORD. |
NATIVE_ARCH_UNDETERMINED | deploy could not tell the NAS architecture for a native app. | Pass --arch x86_64, aarch64 or armv7. |
NATIVE_LAYOUT_INVALID | A native package manifest, hook or file does not follow the package layout rules. | Use schema: 2 with backend.kind: native. Check the paths, that programs are static ELF files, and the checksums. |
NATIVE_TOOLKIT_TAR_UNSUPPORTED | native.toolkits needs GNU tar or bsdtar as tar, and the tar on PATH is neither. | Put GNU tar or bsdtar first on PATH (macOS ships bsdtar; most Linux systems ship GNU tar), then build again. |
NATIVE_LAYOUT_SCRIPT_NOT_EXECUTABLE | A lifecycle script in the native layout scripts/ folder is not executable. DSM runs it directly; inspect reports the same file as SPK_SCRIPT_NOT_EXECUTABLE. | Run chmod +x on the script in the layout metadata folder, then build again. |
NOTICE_MISSING | A third-party license notice file is missing. | Reinstall the template dependencies and rebuild the UI so the notices are generated. |
NOTICE_UNSAFE | A license notice file is a symlink, a special file, or too large. | Remove symlinks, special files and oversized notice files. |
NOT_INSTALLED | The package is not installed on the NAS. | Run synopkgland deploy --host <nas> first. |
PACKAGE_IDENTITY_TOO_LONG | The package name is too long. The limit is 28 characters, so the 4-character .dev suffix still fits in the 32-character DSM limit. | Shorten package to 28 characters or fewer. |
PORT_ALREADY_IN_USE | deploy found that a published TCP port is already used by another service or container. | Change the published host port in synology-app.yaml or compose.yaml. A container of the same package is allowed during upgrade or reinstall. |
PROJECT_NOT_FOUND | No project manifest is found. | Run the command in the project root, or pass --project. |
PROJECT_RUNTIME_EXCLUSIVE | The project has both compose.yaml and dsm-package.yaml. | Keep one: compose.yaml for a container app, dsm-package.yaml for a native app. |
REPRODUCIBLE_INVALID | The reproducible manifest block is malformed, or a listed input is not a file in the project. | Use reproducible: {inputs: [file...], clean: [path...]} with project-relative paths; {arch} is allowed only in clean. |
SHARE_LOGICAL_NAME_REQUIRED | A Shared Folder value is a path such as /volume1/…. | Pass the Shared Folder name shown in Control Panel, for example --share MEDIA_SHARE=photos. |
SHARE_NOT_FOUND | The Shared Folder does not exist on the NAS. | Create it in DSM Control Panel, or fix the spelling. |
SHARE_RUN_AS_NO_ACCESS | The chosen run-as user has no permission on the chosen Shared Folder. The install would succeed but the app would get “Permission denied” at run time. | Give the user (or one of its groups) permission on the Shared Folder in DSM, or pick another user or folder. This check runs only in deploy. The Package Center wizard does not run it. |
SHARE_VALUE_REQUIRED | deploy has no value for a declared shared_folder parameter. | Pass --share <SLOT>=<name>. |
SPK_INSPECTION_FAILED | inspect found at least one error: an SPK rule error in dsm.errors, or, for an SPK built by synopkgland, a build contract problem in findings. | Fix each error in the report, then build or pack again. Warnings do not fail. |
STANDALONE_API_PERMISSIONS_CHANGED | permissions.json changed while the build ran. | Keep the file stable and run check and build again. |
STANDALONE_API_PERMISSIONS_INVALID | permissions.json is not valid. | Fix backend/internal/api/permissions.json. See App API reference. |
STANDALONE_ARCHES_INVALID | arches is not a valid list. | List at least one of x86_64, aarch64, armv7, with no duplicates. |
STANDALONE_ARCH_NOT_DECLARED | The architecture you build is not in arches. | Add it to arches in dsm-package.yaml, or use a declared --arch. |
STANDALONE_BACKEND_INVALID | The backend block is not valid. | Use exactly one of go (dir, and an optional main that starts with ./) or binary (files keyed by architecture). |
STANDALONE_BACKGROUND_ARTIFACT_REQUIRED | The SPK assembler needs the built jobs worker and did not get it. | Build with synopkgland build. Do not call the assembler directly. |
STANDALONE_BACKGROUND_BUILD_FAILED | Building the jobs worker failed. | Install Go 1.25 or later. Check that backend has cmd/background-worker (init -t native-go --with jobs creates it). Read the compiler output. |
STANDALONE_BACKGROUND_INVALID | capabilities.jobs is not valid. | Write jobs: true or jobs: { worker: sha256-v1 }. The worker always runs as the package account. |
STANDALONE_BINARY_ARCH_MISMATCH | A backend program was built for a different CPU than the target. | Rebuild it for that architecture, or fix the mapping in backend.files. |
STANDALONE_BINARY_ARCH_MISSING | An architecture in arches has no program in backend.files. | Add the program, or remove the architecture from arches. |
STANDALONE_BINARY_DYNAMIC | A backend program is dynamically linked. DSM models ship different libc versions. | Link statically. For Go, build with CGO_ENABLED=0. |
STANDALONE_BINARY_MISSING | A backend program is not found. | Check that the file named in backend.files exists. |
STANDALONE_BINARY_NOT_ELF | A backend program is not a little-endian Linux ELF file for its architecture (64-bit for x86_64 and aarch64, 32-bit for armv7). | Provide a Linux program built for that architecture. |
STANDALONE_BINARY_NOT_REGULAR | A backend program is not a regular file. | Use a real file, not a symlink, a folder or a special file. |
STANDALONE_BINARY_TOO_LARGE | A backend program is larger than 256 MiB. | Make it smaller, for example with -ldflags "-s -w". |
STANDALONE_BRIDGE_APP_INVALID | The App directory has a symlink or special file, or is larger than 256 MiB. | Keep only regular files and directories in the App directory, and move large data out of it. |
STANDALONE_BRIDGE_APP_IN_UI | The backend.dir and ui.dir of a Python, Node.js or Rust App overlap; DSM serves the files under ui/ directly. | Put the App in a directory outside ui.dir (for example app/); neither may contain the other. |
STANDALONE_BRIDGE_DESCRIBE_FAILED | Without backend.methods, build starts the App to read its hello, and the App did not answer a v1 hello. | Install python3 or node on the build machine and make sure the App starts, or list backend.methods in dsm-package.yaml. |
STANDALONE_BRIDGE_MANIFEST_INVALID | The bridge.json the CLI wrote does not match the spec/bridge/v1 manifest schema. | Check backend.entry, methods and node.package. If it still fails, report a CLI bug. |
STANDALONE_BRIDGE_METHODS_MISMATCH | The App’s methods do not match permissions.json, or reuse an SDK method name; the runtime refuses to start. | List only the App’s own methods in permissions.json; an App method must not share a name with an SDK method (nas.*, identity.*, portal.status and others). |
STANDALONE_BUILD_INVALID | build is not an integer from 1 to 9999. | Set build to an integer from 1 to 9999. Raise it for each SPK you release. |
STANDALONE_DAEMON_ARTIFACT_REQUIRED | The SPK assembler needs the built daemon supervisor and did not get it. | Build with synopkgland build. Do not call the assembler directly. |
STANDALONE_DAEMON_BUILD_FAILED | Building the daemon supervisor failed. | Install Go 1.21 or later (the build uses exactly Go 1.26.9) and read the compiler output. The NAS does not need Go. |
STANDALONE_DAEMON_INVALID | The daemon block is not valid. | Check daemon.exec, the per-architecture targets, args, env, uninstall_args and the integer-second timeouts. Remove shells, user and custom conf files. |
STANDALONE_DAEMON_PAYLOAD_INVALID | The daemon files are not a bounded folder inside the project without links. | Rebuild each architecture bundle. Remove symlinks, special files and setid bits. Keep the size under 512 MiB. |
STANDALONE_ENTRY_INVALID | entry is not valid. | Use admin-only or app-privilege. app-privilege needs at least one route that permissions.json marks authenticated. |
STANDALONE_ENTRY_WIDENED | entry: admin-only conflicts with a route that permissions.json opens to other users. | Mark those routes administrators. To let ordinary users in, use entry: app-privilege or omit entry. |
STANDALONE_ENTRY_UNSUPPORTED | The backend cannot enforce the entry mode. | Use a Go backend: backend/go.mod requires github.com/synopackageland/syno-pkg-land-sdk, and the main.go of backend.main (cmd/app/main.go after init) wraps the authenticator with dsm.NewEntryGate. |
STANDALONE_FIELD_UNKNOWN | dsm-package.yaml has a field that is not supported. | Remove it. Native packages do not accept custom lifecycle scripts or DSM conf files. |
STANDALONE_GO_BUILD_FAILED | go build failed. | Run go build ./... in the backend folder and fix the errors. |
STANDALONE_GO_MISSING | The go command is not found. | Install Go 1.25 or later from https://go.dev/dl/, or package an existing program with backend.files. |
STANDALONE_I18N_CATALOG_INVALID | A message file is not a flat JSON object of key to text. | Use the form { "greeting.save": "Save" }. |
STANDALONE_I18N_GLOSSARY_INVALID | The glossary file is malformed, or a term points to a message key that does not exist. | Fix terms in glossary.json (id, text, keys). |
STANDALONE_I18N_GLOSSARY_MISMATCH | A message does not use the DSM wording the glossary requires. | Use the glossary term for that language so the app matches DSM. |
STANDALONE_I18N_INVALID | The i18n block is not valid. | i18n accepts only messages, glossary and info. Key info by a supported locale such as zh-TW or ja. Write English at the top level. |
STANDALONE_I18N_KEYS_MISMATCH | A language file has different keys from en.json. | Give every language file exactly the keys of en.json. |
STANDALONE_I18N_LOCALE_UNSUPPORTED | A message file is for a language outside the nine supported ones. | Use en, zh-TW, zh-CN, ja, ko, de, fr, es or it. Other DSM languages show English. |
STANDALONE_I18N_MESSAGES_MISSING | The i18n.messages folder has no en.json. | Add en.json. It is the fallback text and the list of keys for all languages. |
STANDALONE_I18N_PLACEHOLDER_MISMATCH | A translation adds or drops a {placeholder}. | Keep every {name} placeholder from the en.json text. |
STANDALONE_ICON_INVALID | The icon in dsm-package.yaml is not a usable package icon. | Point icon at a square PNG of at least 256×256 inside the project, or an icon_<size>.png directory with icon_256.png. Remove it to use the SDK default icon. |
STANDALONE_MANIFEST_MISSING | dsm-package.yaml is not found. | Run the command in the project root, or create a project with synopkgland init -t native-go. |
STANDALONE_MANIFEST_YAML | dsm-package.yaml is not a valid YAML object. | Fix the YAML syntax. |
STANDALONE_NODE_DEPENDENCY_MISSING | The dependencies in the Node.js App’s package.json are not installed in its node_modules. | Run npm ci --omit=dev in the App directory and build again. The CLI places @synopackageland/app itself. |
STANDALONE_NODE_SDK_NOT_BUILT | The App’s SDK version has no built Node.js SDK (node/dist). | Run npm ci && npm run build in node/ of the SYNOPKGLAND_SDK_DIR checkout first; a released SDK contains node/dist. |
STANDALONE_OS_MIN_VER_INVALID | os_min_ver is not in the right form, or is too low for rootOps. | Use <major>.<minor>-<build>, for example 7.2-64570. rootOps needs 7.1-42661 or later. |
STANDALONE_PACKAGE_INVALID | The package name is not valid. | Start with a letter. Use only letters and digits, 2 to 64 characters, for example PhotoTagger. |
STANDALONE_PATH_INVALID | A path field is not a relative path inside the project. | Use a path relative to the project root. |
STANDALONE_PATH_OUTSIDE_PROJECT | A path points outside the project folder. | Put the file inside the project. A symlink must also resolve inside the project. |
STANDALONE_PORTAL_ENTRY_INVALID | With os_min_ver below DSM 7.2-64570 the executor registers the portal, and the package name or displayname breaks its rules. | The package name may hold only letters and digits separated by ., _ or -, at most 64 characters; displayname is 1–64 characters without control characters. |
STANDALONE_PORTAL_INVALID | portal is malformed or its alias is not valid. | Use portal: {} or portal: { alias: my-app }. The alias is 1 to 64 lowercase letters, digits or -, and is not a reserved DSM path. |
STANDALONE_PORTAL_MIN_DSM | The app declares portal and os_min_ver is below 7.1-42661. | Raise os_min_ver to 7.1-42661 or later, or remove portal. |
STANDALONE_PORTAL_REQUIRES_EXECUTOR | An app without the executor (capabilities.rootOps or delegate) declares portal. | Only root can stop DSM’s web server from serving a Login Portal alias after uninstall, and an app without privileges never uses root. Add root-ops or delegate, or remove portal and let an administrator set up a reverse proxy in DSM. |
STANDALONE_ROOT_OPS_MISSING | capabilities.rootOps: true is set but there is no root operation. | Add at least one root/<name>.sh, or remove capabilities.rootOps. |
STANDALONE_ROOT_OPS_UNUSED | The project has a root/ folder but capabilities.rootOps is not on. | Set capabilities.rootOps: true, or delete root/. |
STANDALONE_ROOT_OP_INVALID | A file in root/ is not a valid root operation. | Each file is root/<lowercase name>.sh, a regular file, starts with #!/bin/sh, and is 16 KiB or smaller. |
STANDALONE_ROOT_PROGRAMS_INVALID | The root settings in dsm-package.yaml are invalid, or the executor does not accept them. | root accepts only programs (<name>: {kind, schema, run, job} for root/<name>.sh or root/<arch>/<name>), stop (a program in root/) and state: true, and needs capabilities.rootOps: true. See Manifest reference. |
STANDALONE_RUNTIME_BUILD_FAILED | Compiling the bridge runtime (bridge/cmd/runtime) of the App’s SDK version failed, or it was not built with go1.26.9. | Install Go 1.21 or later with go1.26.9 available, and use an SDK version that contains the bridge runtime. The message has the compiler output. |
STANDALONE_RUST_BUILD_FAILED | The Rust App’s cargo zigbuild cross-compile failed, or produced no binary for backend.entry. | Install Rust with rustup and the targets x86_64-unknown-linux-musl, aarch64-unknown-linux-musl and armv7-unknown-linux-gnueabihf, plus cargo-zigbuild and zig. Set backend.entry to the Cargo binary name. The message has the compiler output. |
STANDALONE_SCHEMA_INVALID | The schema value is not 2. | Set schema: 2. Use backend.kind and capabilities. |
STANDALONE_SHARED_FOLDER_INVALID | install.sharedFolder is not valid. | Write install: { sharedFolder: { mode: select|create, key: <lowercase letters, digits, underscore>, permission: ro|rw } }. create also needs name. select must not have name. |
STANDALONE_TEXT_INVALID | A display text field is not valid. | Use one non-empty line with no " and no \. For metadata, check the text, email, URLs and screenshots. |
STANDALONE_TIMEOUT_UNSUPPORTED | backend.timeout_seconds needs a Go main that reads the requestTimeout the build passes. | Declare var requestTimeout = "" in main.go and apply it with api.WithRequestDeadline(handler, api.Timeout(...)), or remove timeout_seconds. |
STANDALONE_UI_BUILD_FAILED | The UI build command failed. | Install the UI dependencies in ui.build.cwd (npm ci if there is a package-lock.json, otherwise npm install), run the build command, and fix the errors. |
STANDALONE_UI_BUILD_INVALID | ui.build is not valid. | ui.build.command must be a list of strings, run without a shell, for example [npm, run, build]. |
STANDALONE_UI_ENTRY_MISSING | The UI folder has no app.js or no app.css. | Make ui.dir (or the UI build output) contain both files. |
STANDALONE_UI_INVALID | The ui block is not valid. | Give ui.dir. |
STANDALONE_UI_SPECIAL_FILE | The UI folder has a special file. | Keep only regular files and folders. |
STANDALONE_UI_SYMLINK | The UI folder has a symlink. | Replace it with the real file. |
STANDALONE_UI_TOO_LARGE | The UI files add up to more than 64 MiB. | Make the UI assets smaller. |
STANDALONE_UI_WINDOW_INVALID | ui.window is not a valid DSM window size. | Use whole numbers: width 320–3840 and height 240–2160, with minWidth and minHeight (700 and 420 by default) no larger than them. Write only the fields you change. |
STANDALONE_VERSION_INVALID | version is not a numeric version. | Use a form like 1.2.0. Put the build number in build. |
UNINSTALL_EXEC_MISSING | uninstall.purge.exec is not a regular executable file inside the built package. | Point at an executable in the package, for example ui/cgi/api.cgi, background/worker or a file under daemon/payload/. |
UNINSTALL_EXEC_UNSAFE | uninstall.purge.exec is a shell script that tries to gain root. | The hook always runs as the package account. Put cleanup that needs root in root/<name>.sh and name it in uninstall.purge.root. |
UNINSTALL_INVALID | The uninstall block does not match the fixed exec, argument, environment and timeout contract. | Check uninstall.purge: exec inside the package (not in executor/ or root/), args, env (no SYNOPKGLAND_*) and a timeout of 2–120 seconds, and the unique keys of state.items. |
UNINSTALL_ROOT_OP_MISSING | uninstall.purge.root names a root operation that does not exist. | Add root/<name>.sh, or set uninstall.purge.root to an existing root operation. |
UNINSTALL_ROOT_REQUIRES_ROOT_OPS | uninstall.purge.root needs administrator-approved root operations. | Declare capabilities.rootOps: true and provide root/<name>.sh, or remove uninstall.purge.root. |
UNINSTALL_STATE_REQUIRES_PURGE | uninstall.state has no App uninstall hook that could delete the state. | Add uninstall.purge so the App deletes the listed state when SYNOPKGLAND_DELETE_STATE=1, or remove uninstall.state. |
UNINSTALL_STATE_TEXT_MISSING | The uninstall wizard has no text for an uninstall.state item. | Add uninstall.state.<key> to the en.json message file (and the other languages). |
VALIDATION_FAILED | The project failed contract or safety checks, so deploy stopped. | Run synopkgland check and fix the errors first. |
SPK rules
Section titled “SPK rules”synopkgland inspect <spk> reports these codes in its DSM format section (dsm in --json). They check any SPK against the DSM 7 package format, and the source column names the DSM 7 Developer Guide page each rule comes from. An error fails inspect with SPK_INSPECTION_FAILED. A warning is a likely mistake, or a rule the guide does not state clearly, and does not fail. Each finding in the --json report has code, severity, message and, when it applies, path (a file inside package.tgz is written as package.tgz:<path>).
| Code | Severity | Meaning | Source |
|---|---|---|---|
SPK_CONF_UNKNOWN | warning | conf/ has a file DSM does not read. Known: privilege, resource, PKG_DEPS, PKG_CONX, systemd/. | DSM 7 Developer Guide: conf, Systemd User Unit |
SPK_ELF_ARCH_MISMATCH | error | An ELF executable in package.tgz is for a different CPU than INFO arch. | DSM 7 Developer Guide: INFO Necessary Fields (arch), Appendix A |
SPK_ENTRY_UNKNOWN | warning | The SPK top level has a file or folder the guide does not list. Names are case-sensitive. | DSM 7 Developer Guide: Package Structure |
SPK_ENTRY_UNSAFE | error | A path in the SPK leaves the archive root (absolute or ..), or is a link. | DSM 7 Developer Guide: Package Structure |
SPK_ICON_INVALID | error | PACKAGE_ICON.PNG or PACKAGE_ICON_256.PNG is not a PNG. | DSM 7 Developer Guide: Package Structure |
SPK_ICON_MISSING | error | PACKAGE_ICON.PNG or PACKAGE_ICON_256.PNG is missing. | DSM 7 Developer Guide: Package Structure |
SPK_ICON_SIZE | warning | PACKAGE_ICON.PNG is not 64×64, or PACKAGE_ICON_256.PNG is not 256×256. | DSM 7 Developer Guide: Package Structure |
SPK_INFO_ADMINPORT_INVALID | error | INFO adminport is not an integer from 0 to 65536. | DSM 7 Developer Guide: INFO Optional Fields (adminport) |
SPK_INFO_ARCH_NOARCH_MIXED | warning | INFO arch lists noarch together with other values. | DSM 7 Developer Guide: INFO Necessary Fields (arch) |
SPK_INFO_ARCH_UNKNOWN | warning | INFO arch or exclude_arch has a value that is neither in Appendix A nor a known DSM 7 platform. | DSM 7 Developer Guide: Appendix A Platform and Arch Value Mapping Table |
SPK_INFO_BOOLEAN_INVALID | error | A yes/no INFO field, such as startable or silent_install, is not "yes" or "no". | DSM 7 Developer Guide: INFO Optional Fields |
SPK_INFO_CHECKSUM_MISMATCH | error | INFO checksum is not the MD5 of package.tgz. | DSM 7 Developer Guide: INFO Optional Fields (checksum) |
SPK_INFO_DISPLAYNAME_MISSING | warning | INFO has no displayname, so Package Center shows the package value. | DSM 7 Developer Guide: INFO Optional Fields |
SPK_INFO_FIELD_DUPLICATE | warning | INFO sets the same field twice. | DSM 7 Developer Guide: INFO |
SPK_INFO_FIELD_REQUIRED | error | INFO lacks a necessary field: package, version, os_min_ver, description, arch or maintainer. | DSM 7 Developer Guide: INFO Necessary Fields |
SPK_INFO_FIELD_UNKNOWN | warning | An INFO field is not in the guide’s list, so DSM does not use it. Misspelled field names show up here. | DSM 7 Developer Guide: INFO Necessary Fields, Optional Fields |
SPK_INFO_LANG_UNKNOWN | warning | The language code of displayname_<lang> or description_<lang> is not in the guide’s list (enu, cht, chs, jpn…). | DSM 7 Developer Guide: INFO Optional Fields (description_[language]) |
SPK_INFO_LINE_INVALID | warning | An INFO line is not key="value" (blank lines and # comments are fine). | DSM 7 Developer Guide: INFO |
SPK_INFO_MISSING | error | INFO is missing. | DSM 7 Developer Guide: Package Structure |
SPK_INFO_OS_MIN_VER_LOW | warning | INFO os_min_ver is below 7.0-40000. | DSM 7 Developer Guide: INFO Necessary Fields (os_min_ver) |
SPK_INFO_OS_VER_INVALID | error | INFO os_min_ver or os_max_ver is not <major>.<minor>-<build> (<major>.<minor>.<micro>-<build> is also accepted). | DSM 7 Developer Guide: INFO Necessary Fields (os_min_ver), Optional Fields (os_max_ver) |
SPK_INFO_PACKAGE_INVALID | error | INFO package contains one of : / > < | =. | DSM 7 Developer Guide: INFO Necessary Fields (package) |
SPK_INFO_VALUE_UNTERMINATED | error | An INFO value has no closing quote. | DSM 7 Developer Guide: INFO |
SPK_INFO_VERSION_INVALID | error | INFO version is not numbers separated by ., - or _, or a part is above 2147483647. | DSM 7 Developer Guide: INFO Necessary Fields (version) |
SPK_INFO_VERSION_NO_BUILD | warning | INFO version has no -<build> number; the guide’s form is [feature number]-[build number]. | DSM 7 Developer Guide: INFO Necessary Fields (version) |
SPK_LICENSE_TOO_LARGE | error | LICENSE is 1 MB or larger. | DSM 7 Developer Guide: Package Structure |
SPK_NOARCH_ELF | error | INFO arch is noarch, but package.tgz contains an ELF executable. | DSM 7 Developer Guide: INFO Necessary Fields (arch), Pack Stage |
SPK_NOT_TAR | error | The file is not a readable tar archive. An SPK is an uncompressed tar. | DSM 7 Developer Guide: Package Structure |
SPK_PAYLOAD_LINK_ABSOLUTE | warning | A package.tgz symlink points to an absolute path, so the NAS, not the package, decides its target. | DSM 7 Developer Guide: Package Structure (package.tgz) |
SPK_PAYLOAD_LINK_ESCAPE | error | A package.tgz symlink or hard link points outside the package folder. | DSM 7 Developer Guide: Package Structure (package.tgz) |
SPK_PAYLOAD_MISSING | error | package.tgz is missing. | DSM 7 Developer Guide: Package Structure |
SPK_PAYLOAD_PATH_UNSAFE | error | A package.tgz path is absolute or contains .., so it would extract outside the package folder. | DSM 7 Developer Guide: Package Structure (package.tgz) |
SPK_PAYLOAD_UNREADABLE | error | package.tgz is not a readable tar or tar.gz archive, or it is empty. | DSM 7 Developer Guide: Package Structure (package.tgz) |
SPK_PAYLOAD_XZ | warning | package.tgz is xz-compressed (the Synology toolkit format). inspect cannot read xz, so the payload rules did not run. | DSM 7 Developer Guide: Pack Stage |
SPK_PRIVILEGE_INVALID | error | conf/privilege is not a JSON object, has no defaults.run-as, or a run-as is not package or root. | DSM 7 Developer Guide: Privilege Config |
SPK_PRIVILEGE_MISSING | error | conf/privilege is missing. DSM 7 requires it. | DSM 7 Developer Guide: conf, Privilege Config |
SPK_PRIVILEGE_ROOT | warning | conf/privilege asks to run as root (in defaults, ctrl-script or executable). | DSM 7 Developer Guide: Privilege Config |
SPK_RESOURCE_INVALID | error | conf/resource is not a JSON object. | DSM 7 Developer Guide: Resource Config |
SPK_RESOURCE_UNKNOWN | warning | conf/resource has a resource worker id the guide does not list. | DSM 7 Developer Guide: Available Workers |
SPK_SCRIPT_HOOK_MISSING | warning | preinst, postinst, preuninst, postuninst, preupgrade or postupgrade is missing. The guide marks them required; what DSM does without one is not verified. | DSM 7 Developer Guide: scripts |
SPK_SCRIPT_MISSING | error | scripts/start-stop-status is missing. DSM uses it to start, stop and poll the package. | DSM 7 Developer Guide: Package Structure, scripts |
SPK_SCRIPT_NOT_EXECUTABLE | error | A lifecycle script in scripts/ is not executable. | DSM 7 Developer Guide: scripts |
SPK_SCRIPT_NO_INTERPRETER | warning | A lifecycle script starts with no #! line (such as #!/bin/sh) and is not ELF. | DSM 7 Developer Guide: scripts |
SPK_SIGNATURE_INVALID | warning | syno_signature.asc is not an ASCII-armored PGP signature. The guide’s package signing applies only to DSM 6.x, so the file can be left out. | DSM 7 Developer Guide: Sign Package (only for DSM6.X) |
SPK_UI_CONFIG_INVALID | error | The config under dsmuidir is not a JSON object. | DSM 7 Developer Guide: Integrate DSM, Application Config |
SPK_UI_TEXTS_MISSING | error | A config title or desc refers to the package’s own strings (for example synopkgland:app_title), but the entry does not declare "texts", so DSM shows the raw key. | Tested on DSM 7.1.1 and 7.4 |
SPK_UI_TEXTS_UNDECLARED | warning | A config title or desc is a section:key reference without "texts". Unless the section is built into DSM, DSM shows the raw key. | Tested on DSM 7.1.1 and 7.4 |
SPK_WIZARD_INVALID | warning | A wizard file in WIZARD_UIFILES is not a JSON array. | DSM 7 Developer Guide: Package Structure (WIZARD_UIFILES) |
SPK_WIZARD_SCRIPT_NOT_EXECUTABLE | warning | A .sh wizard generator in WIZARD_UIFILES is not executable. | DSM 7 Developer Guide: Package Structure (WIZARD_UIFILES) |
SPK_WIZARD_UNKNOWN | warning | A WIZARD_UIFILES name is not install, upgrade or uninstall_uifile[_<lang>][.sh]. | DSM 7 Developer Guide: Package Structure (WIZARD_UIFILES) |
App errors
Section titled “App errors”A generated native app returns these codes from its backend to the UI. A handler can also return its own codes; see App API reference.
Errors that a handler returns as a plain Go error, not as api.Error, reach the UI as internal. This includes every failure of root.run, and every failure of executor.status except a paused executor, which answers ready: false with state: "paused" and a next step.
| Code | Returned by | Meaning | What to do |
|---|---|---|---|
session_required | Every route except public ones | There is no valid DSM session, or the File Station user does not match the caller. | Sign in to DSM again. |
credential_not_ready | Routes that act with the caller’s DSM session (root.*, files.*, delegate.*, File Station) | The request has a DSM session cookie but no usable SynoToken. The shared window wrapper obtains a missing token before backend and DSM WebAPI calls; this error means the required carrier is still unavailable. | Sign in to DSM again on the same host and reopen the app. In a custom transport, await the DSM session helper before sending the request. |
dsm_session_required | nas.*, bg.browse, bg.jobs.submit with identity: standalone | The call needs the DSM id cookie and it is missing. | Open the app from the DSM window and sign in to DSM. |
session_revalidation_required | Other routes with identity: standalone | The app session needs to be checked against DSM and the DSM cookie is missing. | Open the app from the DSM window. |
admin_required | Routes that need administrators | The caller is not in the DSM administrators group, entry: admin-only refused the caller, or api.RequireAdmin failed. A registered method that permissions.json does not list also gives this code to non-administrators. | Open the app with an administrator account. An admin-only app is not listed in Application Privileges. If the method is intended for ordinary users, list it as authenticated in permissions.json. |
app_privilege_denied | Every route when entry: app-privilege | DSM Application Privileges do not allow this account or address to use the app. | Ask an administrator to open Control Panel > Application Privileges, select the app by its display name and click Edit, then allow your account or group. |
auth_unavailable | Every route | DSM authentication or the privilege lookup failed. It is also returned when there are too many sessions. | Retry. If it persists, check that DSM is healthy. |
unknown_method | Every route | The method name is not registered. Every signed-in caller gets this code, administrator or not. | Check the method name and that the capability is added. |
cross_origin | JSON routes | The request came from another origin. | Call the backend only from the app’s own page. |
origin_required | JSON routes | A POST carried neither Origin nor Referer, so the backend cannot tell which page sent it. | Open the app again in a current browser. |
json_required | JSON routes | The request does not have Content-Type: application/json. | Send JSON. ctx.call does this for you. |
method_not_allowed | JSON routes | The request is not a POST. | Use POST. |
request_too_large | JSON routes | The body is larger than 1 MiB or too deeply nested. | Send less data. |
bad_request | Every route | The body or the params are not valid. Params with unknown fields are refused. | Send {"method": "…", "params": {…}} with only the fields the method accepts. |
bad_response | Every route | The request timed out (20 seconds) or was canceled, or the server did not return JSON. | Retry. |
internal | Every route | The handler returned an error that is not an api.Error. The details are in the app log, not in the response. | Return api.Error for errors the UI should see. Check the app log. |
network | ctx.call in the DSM window | The NAS did not answer. | Check the connection and retry. |
denied | nas.*, bg.browse | File Station refused the operation, usually because the user lacks permission on the folder. | Give the user permission on the folder in DSM. |
conflict | nas.*, bg.* | The target already exists, or the request conflicts with the current state of the job. | Pick another name, or reload the state. |
invalid-request | nas.* | File Station refused the arguments, for example a bad path. | Check the path. |
unavailable | nas.*, bg.* | File Station or the background storage did not answer or is not available. | Retry later. |
canceled | nas.*, delegate.* | The call was canceled. | Retry if you did not cancel it. |
not_found | nas.*, bg.jobs.* | The file, job or schedule does not exist, or belongs to another user. | Check the path or id. |
commit-uncertain | nas.files.create_folder, nas.files.upload | The response was lost, so you cannot tell if the change was made. | List the folder to check, then retry if needed. |
upload_size_required | nas.files.upload | The upload has no Content-Length, or it is larger than 16 GiB. | Send a Content-Length of at most 16 GiB. |
limit-exceeded | nas.*, bg.jobs.submit, files.read | A size limit was reached, for example a job input larger than 512 KiB. | Send a smaller file. |
read_failed | bg.jobs.submit | The file could not be read completely. | Retry. |
identity_unavailable | bg.* | The caller’s DSM user id could not be found. | Retry. If it persists, sign in to DSM again. |
jobs_busy | bg.* | The job store stayed locked for 5 seconds. | Retry later. |
not_ready | bg.jobs.result | The job has no result yet. | Wait until the job is succeeded. |
queue-full | bg.jobs.submit, bg.schedules.* | The background queue is full. | Wait for jobs to finish. |
quota-exceeded | bg.jobs.submit | The background storage is full. | Wait for jobs to finish, or remove finished jobs. |
owner-queue-full | bg.jobs.submit | The caller already has the maximum of pending jobs. | Wait for the caller’s jobs to finish. |
owner-quota-exceeded | bg.jobs.submit | The caller’s background storage limit is reached. | Wait for the caller’s jobs to finish. |
schedule-full | bg.schedules.create | The schedule limit of the package is reached. | Delete a schedule. |
input-unavailable | bg.schedules.* | The private copy of the job input is gone. | Import the file again. |
https_required | identity.login, identity.session | The call was made over plain HTTP. | Open the app over HTTPS. |
invalid_credentials | identity.login | The account name or password is wrong. | Try again. |
account_disabled | identity.login | The DSM account is disabled. | Use another account, or enable it in DSM. |
otp_required | identity.login | The account needs a two-factor code. | Send otp with the login. |
login_not_permitted | identity.login | DSM does not let this account sign in to the app. | Check the account in DSM. |
rate_limited | identity.login | Too many attempts. | Wait a minute and retry. |
invalid-destination | delegate.* | The destination is not valid. | Select the destination again. |
invalid-size | delegate.* | The file size is not valid. | Pass the real size of the staged file. |
unsupported | delegate.*, bg.* | The call is not supported in this setup. | Check the capability and the lifetime mode. |
needs-scope-confirmation | delegate.* | An administrator must confirm the folder scope first. | Approve the scope in the app’s administrator settings. |
disabled | delegate.* | An administrator turned the integration off. | Ask an administrator to enable it. |
operation-conflict | delegate.* | The same job id was sent again with different input. | Use a new job id. |
operation-not-found | delegate.operations.* | The operation is not known to the executor. | Check the ids. |
destination-exists | delegate.move_from_staging, delegate file operations | A file with that name already exists in the destination, and conflict is fail; or overwrite met a folder or symlink; or rename used up name (99). | Use another name, or set conflict. |
invalid-path | delegate.move_from_staging, delegate file operations | A folder in name is empty, . or .., longer than 255 bytes, contains a control character or one of \ : * ? " < > |, or is #recycle, #snapshot or @eaDir; or the whole name is longer than 1024 bytes; or File Station refused a name or path as illegal. | Fix the name. |
path-too-deep | delegate.move_from_staging | name has more than 16 folders. | Use fewer folders. |
destination-not-directory | delegate.move_from_staging, files.createFolder | A folder in name exists as a file or a symlink, or is on another volume; or CreateFolder was called below a file. | Choose another folder name. |
name-too-long | delegate.move_from_staging, delegate file operations | The volume refused a name as too long, for example over 143 bytes on an encrypted Shared Folder. | Use a shorter name. |
NO_SPACE | delegate.move_from_staging, delegate file operations | The destination volume is full. | Free space. |
not-found | Delegate file operations | The path does not exist inside the grant’s folder, or File Station reported the item missing. | Check the path. |
not-a-file | files.read | The path is a folder or a special file. | Read a regular file. |
recursive-required | files.delete | The path is a folder and recursive is not set. | Set Recursive: true. |
recycle-bin-disabled | files.delete | The Shared Folder has no recycle bin and permanent is not set. | Turn on the recycle bin, or set Permanent: true. |
task-not-found | files.taskStatus, files.taskCancel | The task belongs to another job, or the executor restarted. | Check the result with files.info. |
too-many-tasks | files.copy, files.move, files.delete | The executor already tracks 64 tasks. | Wait for tasks to finish. |
READ_FAILED | files.read | The executor could not copy the file into staging. | Retry. If it persists, check the NAS. |
PERMISSION_DENIED | delegate.* | The user the app acts for cannot write to the destination, delegate.select_destination was given a folder the user cannot write to, or File Station refused an item for lack of permission. A delete that leaves the item behind also fails with it. | Fix permissions in DSM, or choose another destination. |
STAGING_UNAVAILABLE, STAGING_CHANGED | delegate.move_from_staging | The staged file is missing, or it changed after you staged it. | Stage the file again. |
ADMISSION_PENDING, ADMISSION_EXHAUSTED | delegate.move_from_staging | The move is waiting to be accepted by the executor, or it ran out of retries. | Wait and check delegate.operations.get. |
download_failed | Delegate time-limited downloads | The download did not finish. | Retry. |
jobs_unavailable | delegate.jobs.* | The job store is not available. | Retry later. |
spool_unsafe, journal_corrupt | delegate.jobs.* | The job store failed a safety check. | These do not clear on retry. Check the app data folder. |
not_cancelable, key_conflict, queue_full, quota | delegate.jobs.* | The job cannot be canceled in its state, the key is already used, the queue is full, or storage is full. | Change the request or wait. |
EXECUTOR_UNAVAILABLE, EXECUTOR_TIMEOUT, EXECUTOR_TOO_LARGE, EXECUTOR_PROTOCOL | delegate.*, executor.* | The app could not reach the administrator-operations executor, it timed out, the message was too large, or the answer was not understood. | Check the capability state with synopkgland status. An administrator may need to approve it again. |
EXECUTOR_PAUSED | delegate.* | The executor is paused, for example while the package is stopped or upgraded. | Start the package. An administrator may need to approve it again after an upgrade. |
APP_STOPPED, APP_STARTING | delegate.*, executor.* | The package is stopped, or was just started and its executor is not listening yet. Nothing was sent. | Start the package, or wait: the SDK’s panels show the stopped or starting package and check again on their own, and an action they refuse reads “start it, then try again” (lifecycleRefusal(error, locale)). The DSM window passes APP_STOPPED on at once and repeats APP_STARTING and EXECUTOR_STARTING for about 4 seconds; executor.control repeats a start for up to 30 seconds. |
AUTH_DENIED, INELIGIBLE, APP_DENIED, ADMIN_REQUIRED, DELEGATION_DENIED, SCOPE_DENIED, POLICY_DENIED, UNKNOWN_OP | delegate.* | The executor refused the operation: the caller or app is not allowed, the grant or folder scope does not cover it, or the operation is not in the approved policy. | Check the grant, the scope and the manifest. Changing the policy needs a rebuild and a new administrator approval. |
INVALID_REQUEST, REQUEST_TOO_LARGE | delegate.* | The request to the executor is not valid or is larger than 64 KiB. The Go client returns INVALID_REQUEST before it calls the executor when a path or name is not valid. | Fix the request. |
STORAGE_ERROR, INTERNAL, WRITE_FAILED, DSM_FAILED | delegate.* | The executor failed while reading its state, writing the file or calling DSM. | Retry. If it persists, check the NAS. |
SCOPE_APPROVAL_STALE, IDENTITY_CHANGED | delegate.* | The scope approval is out of date, or the DSM account the grant belongs to changed. | Approve the scope or select the destination again. |
ROOT_FAILED | root.run (shown as internal) | The root operation exited with a non-zero status or failed to run. | Test the script. Output is capped at 1 MiB and the run at 20 seconds. |
portal_alias_invalid | ctx.portal | DSM rejected the alias. | Use 1 to 64 lowercase letters, digits or -. |
portal_alias_reserved | ctx.portal | The alias is a reserved DSM path. | Choose another alias. |
portal_alias_in_use | ctx.portal | Another app already uses the alias. | Choose another alias. |
portal_unavailable | ctx.portal | Application Portal settings could not be read or changed. | Retry. Use Control Panel if it persists. |
forbidden | Container app sign-in gateway | The signed-in user is not allowed by the app’s integration.web.access. | Add the user to an allowed group, or change access. |
token_required | Container app sign-in gateway | A request other than GET, HEAD or OPTIONS has no DSM token. | Send the X-SYNO-TOKEN header. |
cross_site_blocked | Container app sign-in gateway | A state-changing request or WebSocket handshake came from another site. | Call only from the app’s own page. |
upgrade_unsupported | Container app sign-in gateway | The request asked for a protocol upgrade that the gateway does not support. | Use plain HTTP or WebSocket. |
redirect | Container app sign-in gateway | The path needs a trailing slash. | Follow the redirect (HTTP 308). |
bad_path | Container app sign-in gateway | The request path is not valid. | Fix the URL. |
body_too_large | Container app sign-in gateway | The request body is larger than 64 MiB. | Send less data. |
upstream_timeout | Container app sign-in gateway | The container did not answer within 60 seconds. | Check the container. |
upstream_unavailable | Container app sign-in gateway | The container is not reachable. | Check that the container is running. |
bad_gateway | Container app sign-in gateway | The gateway could not get a valid answer from the container. | Check the container log. |
The sign-in gateway returns plain-text errors: the first line is the code. It also sets the X-Synopkgland-Error header. DSM replaces some error statuses with its own page, so the gateway sends a different status and puts the intended one in X-Synopkgland-Status: 403 as 401, 404 as 410, 500 and 502 as 520, 503 as 521, and 504 as 524.
Delegate file operations read File Station’s per-item refusals, so PERMISSION_DENIED, destination-exists, not-found, name-too-long, invalid-path, destination-not-directory and NO_SPACE name the real cause. They are not retryable.
A job that fails has an errorCode instead of an RPC error. Read it from bg.jobs.get or bg.jobs.list.
errorCode | Meaning | What to do |
|---|---|---|
timeout | The job ran longer than 60 seconds. | Use a smaller input. |
input-changed | The worker result did not match the input digest. | Submit the job again. |
worker-error | The worker failed. | Submit the job again. If it repeats, check the input. |
worker-stopped | The worker stopped while the job ran. The job state is interrupted. | Submit the job again. |
worker-changed | The worker version changed after you queued the job. The job state is interrupted, and schedules stay off until an administrator enables them. | Submit the job again. An administrator enables the schedules with bg.schedules.enable. |
admission-interrupted | The job was interrupted before it was accepted. | Submit the job again. |
Executor protocol codes
Section titled “Executor protocol codes”The administrator-operations executor answers the app backend with these codes. They are the codes of executor protocol v1 in @synopackageland/sdk and the Go module github.com/synopackageland/syno-pkg-land-sdk; this table is generated from its errors.json. kind says where a code appears: refusal is a refused request, outcome and reason are recorded on an operation, and client is produced by the client in the app, never sent by the executor. The app backend passes most of them to the UI as listed under App errors.
| Code | Kind | Retryable | HTTP | Meaning |
|---|---|---|---|---|
AUTH_DENIED | refusal | No | 401 | The DSM session in auth is missing, invalid or expired. |
INELIGIBLE | refusal | No | 403 | The DSM account cannot be delegated: system account, expired, or not the caller. |
APP_DENIED | refusal | No | 403 | DSM Application Privileges do not allow the account to use the app or File Station. |
ADMIN_REQUIRED | refusal | No | 403 | The operation needs a DSM administrator. |
DELEGATION_DENIED | refusal | No | 403 | The grant does not exist, belongs to another user or package, or was revoked. |
SCOPE_DENIED | refusal | No | 403 | The path is outside the grant or the approved folder scope. |
POLICY_DENIED | refusal | No | 403 | The operation is not in the approved policy. |
PEER_DENIED | refusal | No | 403 | The socket peer is not the package user or root. |
PERMISSION_DENIED | refusal | No | 403 | The delegated user cannot access the path in DSM. |
UNKNOWN_OP | refusal | No | 400 | The executor does not know the operation. |
INVALID_REQUEST | refusal | No | 400 | The request or its params are not valid. |
REQUEST_TOO_LARGE | refusal | No | 413 | The request line is larger than 64 KiB. |
EXECUTOR_PAUSED | refusal | Yes | 503 | The executor is paused, for example while the package stops or upgrades. |
EXECUTOR_STARTING | refusal | Yes | 503 | The executor is running the App’s start step after an install or upgrade; status answers state starting until it ends. |
STORAGE_ERROR | refusal | Yes | 500 | The executor could not read or write its protected state. |
INTERNAL | refusal | Yes | 500 | The executor failed unexpectedly. |
WRITE_FAILED | refusal | Yes | 500 | The executor could not write the file. |
READ_FAILED | refusal | Yes | 500 | The executor could not copy the file into staging. |
DSM_FAILED | refusal | Yes | 502 | A DSM call made by the executor failed. |
ROOT_FAILED | refusal | No | 500 | The root program could not run, ended by a signal, or its output could not be kept. |
ROOT_TIMEOUT | refusal | Yes | 504 | The root program ran past its policy timeout and was killed. |
ROOT_BUSY | refusal | Yes | 429 | The package already runs as many root programs as it may. |
ROOT_STAGING_FULL | refusal | Yes | 507 | Root output waiting in the staging folder already fills its quota. |
ROOT_JOB_NOT_FOUND | refusal | No | 404 | No root job of the package has this job_id. |
PORTAL_FAILED | refusal | Yes | 502 | DSM did not accept the Application Portal change; status portal says whether the entry needs another removal. |
NO_SPACE | refusal | No | 507 | The destination volume is full. |
SCOPE_APPROVAL_STALE | refusal | No | 409 | The folder scope approval is out of date. |
IDENTITY_CHANGED | refusal | No | 409 | The DSM account or folder the grant is bound to changed. |
needs-scope-confirmation | refusal | No | 409 | An administrator must confirm the folder scope first. |
disabled | refusal | No | 409 | An administrator turned the integration off. |
invalid-destination | refusal | No | 400 | The destination key is not in the policy. |
invalid-size | refusal | No | 400 | The size is missing, negative or too large. |
operation-conflict | refusal | No | 409 | The same job id was sent again with different input. |
operation-not-found | refusal | No | 404 | The operation is not known for this grant and caller. |
destination-exists | refusal | No | 409 | A file with that name already exists and conflict does not allow replacing it. |
invalid-path | refusal | No | 400 | A name or path is empty, reserved, too long or contains a forbidden character. |
path-too-deep | refusal | No | 400 | The name has more than 16 folders. |
destination-not-directory | refusal | No | 409 | A folder in the name exists as a file or symlink, or is on another volume. |
name-too-long | refusal | No | 400 | The volume refused a name as too long. |
not-found | refusal | No | 404 | The path does not exist. |
not-a-file | refusal | No | 400 | The path is a folder or a special file. |
recursive-required | refusal | No | 400 | The path is a folder and recursive is not set. |
recycle-bin-disabled | refusal | No | 409 | The Shared Folder has no recycle bin and permanent is not set. |
task-not-found | refusal | No | 404 | The task belongs to another job, or the executor restarted. |
too-many-tasks | refusal | Yes | 429 | The executor already tracks 64 tasks. |
queue-full | refusal | Yes | 429 | The executor operation queue is full. |
limit-exceeded | refusal | No | 413 | The file is larger than max_bytes, or root output is larger than its policy max_output. |
OPERATION_CANCELED | outcome | No | 409 | The operation was canceled; reason says why. |
CANCEL_REQUESTED | outcome | No | 202 | Cancel was requested and the copy has not stopped yet. |
CLEANUP_PENDING | outcome | Yes | 500 | The operation ended but its partial file is not removed yet. |
grant-revoked | reason | No | 409 | The grant was revoked. |
destination-replaced | reason | No | 409 | A newer grant replaced this destination. |
integration-disabled | reason | No | 409 | An administrator disabled the integration. |
validation-denied | reason | No | 403 | The grant failed revalidation against DSM. |
scope-changed | reason | No | 409 | The approved folder scope changed. |
storage-error | reason | Yes | 500 | Protected state could not be written. |
operation-canceled-by-user | reason | No | 409 | The owner canceled the operation. |
operation-deadline-exceeded | reason | Yes | 504 | The operation ran past its deadline. |
EXECUTOR_UNAVAILABLE | client | Yes | 503 | The client could not connect to the executor socket. |
APP_STOPPED | client | Yes | 503 | The package is stopped: its lifecycle mailbox asks the executor to stop. The client sent nothing. |
APP_STARTING | client | Yes | 503 | The package was just started and its executor is not listening yet. The client sent nothing. |
EXECUTOR_TIMEOUT | client | Yes | 504 | The executor did not answer in time. |
EXECUTOR_TOO_LARGE | client | No | 413 | The request or reply is larger than 64 KiB. |
EXECUTOR_PROTOCOL | client | No | 502 | The executor reply is not a valid v1 response. |