Confirm whether the installed version can contain the historical bug
Syncthing issue 8503 covers a historical reflect error when syncthing cli config devices add was used with --addresses. The fix is listed in the Syncthing 1.23.5 release. Assuming the same bug on a current installation can hide a different config home, the wrong device ID, or REST array-replacement behavior.
The diagnostic authority is not a CLI success message; it is the device object stored by the running Syncthing instance. Record the config directory and GUI API used by that instance, then read its address array through the REST API.
Freeze the values that identify the configuration
| Item | Evidence | Possible mismatch |
|---|---|---|
| Binary | Path and Syncthing version | An old CLI or another installation is running. |
| Config home | config.xml and database paths | The service and shell address different instances. |
| Device identity | The exact device ID | A different device object was edited. |
| Addresses array | dynamic and static URI entries | A PATCH replaced the previous array. |
| Restart state | The restart-required API result | The value is saved but awaits restart. |
syncthing --version
syncthing paths
syncthing cli config devices add --device-id <DEVICE_ID> --name <NAME> --addresses tcp://192.0.2.42:22000
Include a protocol prefix in an address URI. Syncthing configuration documentation defines TCP and QUIC forms, default ports, and the dynamic value. Whether to use only a static address or retain dynamic for discovery fallback is an operational choice.
Read the stored object through the REST API
This example targets Linux/macOS Bash and curl with header-file support. Read the API key with hidden input and store it in a header file under a restricted directory. Do not type the key into a command or export it; curl receives only the file path. This does not prevent the same user or an administrator from reading memory or files. Use a private terminal without debugging or session recording. Run these GETs and the following PATCH in the same script. On exit, remove only the key file; the backup remains in the private WORK directory. Do not share configuration responses. For a TLS GUI, use its actual HTTPS URL and trusted certificate; never disable verification with -k.
# Bash on Linux/macOS; save as a script, do not enable xtrace.
set +x
set -euo pipefail
umask 077
WORK=$(mktemp -d "${TMPDIR:-/tmp}/syncthing-check.XXXXXXXX")
trap 'rm -f -- "$WORK/api-header"' EXIT
IFS= read -r -s -p 'Syncthing API key: ' ST_API_KEY
printf '
'
printf 'X-API-Key: %s
' "$ST_API_KEY" > "$WORK/api-header"
unset ST_API_KEY
DEVICE_ID='REPLACE_WITH_DEVICE_ID'
API='http://127.0.0.1:8384'
curl -q -fsS --header "@$WORK/api-header" \
"$API/rest/config/devices/$DEVICE_ID" > "$WORK/device-before.json"
curl -q -fsS --header "@$WORK/api-header" "$API/rest/config/restart-required"
Header delivery was tested using a synthetic key and a localhost mock HTTP server. This does not reproduce PATCH behavior in a particular Syncthing build.
PATCH replaces a child array; it does not append
Syncthing’s REST documentation says PATCH overlays JSON on the existing object, but child arrays are replaced rather than extended. Sending one new entry in addresses can remove dynamic and other static entries. Submit the complete desired final array.
curl -q -fsS -X PATCH \
--header "@$WORK/api-header" \
-H 'Content-Type: application/json' \
--data '{"addresses":["tcp://192.0.2.42:22000","dynamic"]}' \
"$API/rest/config/devices/$DEVICE_ID"
curl -q -fsS --header "@$WORK/api-header" "$API/rest/config/devices/$DEVICE_ID"
curl -q -fsS --header "@$WORK/api-header" "$API/rest/config/restart-required"
Interpret the saved result
- The version predates 1.23.5: issue 8503 can be relevant. Review that release and the active package channel, update to a supported version, and repeat the test.
- The REST object lacks the address after the CLI command: verify CLI arguments, device ID, and config home. Confirm that the shell did not call a different Syncthing instance.
- The REST object contains it but the connection does not use it: this is no longer a storage problem. Inspect URI syntax, destination listen address, firewall, and connection logs.
- Existing entries disappear after PATCH: that is array replacement. Combine the backup addresses with the new entry and PATCH the complete final array.
- restart-required is true: review active transfers and perform a planned restart. Saving configuration and establishing a connection are separate results.
Rollback and verification
If the change fails, recover the original addresses array from $WORK/device-before.json and PATCH only that field. PUT of the complete old device object can revert unrelated fields that changed during the investigation.
After restoration, repeat REST GET and inspect the connection log. Remove the API key from the shell and restrict backup permissions. If dynamic remains, Syncthing can connect through discovery even when the static address fails, so confirm the address actually used.
Related guides
Official references
- Syncthing issue 8503 – historical CLI bug combining devices add with addresses
- Syncthing 1.23.5 release – version containing the issue 8503 fix
- Syncthing configuration – device address URIs, dynamic, and config locations
- Syncthing config REST endpoints – GET, PATCH, array replacement, and restart-required behavior
- Syncthing command line – paths, config and data homes, and CLI scope
Earlier verification notes preserved from this article
Verification level: official documentation checked
The historical CLI fix and current REST configuration behavior were compared using the official issue, release, and documentation. No specific package build was reproduced, so the current installation is not assumed to have the same bug.