syncthing/syncthing · error

%q: device ID invalid: incorrect length

Error message

%q: device ID invalid: incorrect length

What it means

DeviceID.UnmarshalText/String parse rejects a candidate device ID whose length matches none of the supported encodings: 63 chars (new style, 56 + 7 dashes), 59 (with trailing checksum digit variant), or 52 (old style, raw base32). The input is simply not a device ID in any accepted format — most commonly truncated copy-paste or stray characters.

Source

Thrown at lib/protocol/deviceid.go:151

		*n = EmptyDeviceID
		return nil
	case 56:
		// New style, with check digits
		id, err = unluhnify(id)
		if err != nil {
			return err
		}
		fallthrough
	case 52:
		// Old style, no check digits
		dec, err := base32.StdEncoding.DecodeString(id + "====")
		if err != nil {
			return err
		}
		copy(n[:], dec)
		return nil
	default:
		return fmt.Errorf("%q: device ID invalid: incorrect length", bs)
	}
}

func (*DeviceID) ProtoSize() int {
	// Used by protobuf marshaller.
	return DeviceIDLength
}

func (n *DeviceID) MarshalTo(bs []byte) (int, error) {
	// Used by protobuf marshaller.
	if len(bs) < DeviceIDLength {
		return 0, errors.New("destination too short")
	}
	copy(bs, (*n)[:])
	return DeviceIDLength, nil
}

func (n *DeviceID) Unmarshal(bs []byte) error {

View on GitHub (pinned to 058bcd7334)

Solutions

  1. Re-copy the full device ID from the remote's 'Actions > Show ID' screen — it must be 63 characters including dashes.
  2. Strip whitespace/newlines from the input before parsing.
  3. Verify you are not passing a certificate SHA256 fingerprint or API key instead of the device ID.
  4. Validate length and charset (A-Z2-7 plus dashes) before storing it in config.

Example fix

// before
id, err := protocol.DeviceIDFromString(userInput)

// after
clean := strings.TrimSpace(strings.Join(strings.Fields(userInput), ""))
if len(clean) != 63 && len(clean) != 52 {
    return fmt.Errorf("expected 63-char device ID, got %d chars", len(clean))
}
id, err := protocol.DeviceIDFromString(clean)
Defensive patterns

Strategy: validation

Validate before calling

// Validate shape before parsing a device ID from user input
func looksLikeDeviceID(s string) bool {
    s = strings.ReplaceAll(strings.TrimSpace(s), "-", "")
    for _, c := range s {
        if !(c >= 'A' && c <= 'Z' || c >= '2' && c <= '7') { return false }
    }
    return len(s) == 52 || len(s) == 56 // old style raw, or new style with check digits
}

Try / catch

id, err := protocol.DeviceIDFromString(input)
if err != nil {
    // covers 'incorrect length' plus check-digit/charset errors;
    // re-prompt the user to paste the full 63-char ID (QR code preferred)
    return fmt.Errorf("invalid device ID %q: %w", input, err)
}

Prevention

When it happens

Trigger: protocol.DeviceID from user input; config load with a <device id=...> attribute that is truncated or contains extra whitespace/newlines; passing a 44-char base32 key or a SHA-256 hex string instead of the 63-char formatted ID.

Common situations: Copy-pasting a device ID missing the last group; pasting a certificate fingerprint (hex) instead of the Syncthing device ID; whitespace or quotes accidentally included when scripting config edits.

Related errors


AI-assisted analysis of syncthing/syncthing@058bcd7334 (2026-08-15). Data as JSON: /api/errors/0aba34834545a098. Report an issue: GitHub.