AlistGo/alist · error
rename failed with code %d
Error message
rename failed with code %d
What it means
Proton answered 200 but the JSON body's Code field is not 1000 (the success code). This is the API-level rejection of the rename: common Proton codes include 401-equivalents (invalid token), 2029/2028-style hash mismatches (Hash or OriginalHash wrong), and duplicate-name conflicts in the target folder.
Source
Thrown at drivers/proton_drive/util.go:666
client := &http.Client{}
resp, err := client.Do(httpReq)
if err != nil {
return fmt.Errorf("failed to execute rename request: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("rename failed with status %d", resp.StatusCode)
}
var renameResp RenameResponse
if err := json.NewDecoder(resp.Body).Decode(&renameResp); err != nil {
return fmt.Errorf("failed to decode rename response: %w", err)
}
if renameResp.Code != 1000 {
return fmt.Errorf("rename failed with code %d", renameResp.Code)
}
return nil
}
func (d *ProtonDrive) executeMoveAPI(ctx context.Context, linkID string, req MoveRequest) error {
//fmt.Printf("DEBUG Move Request - Name: %s\n", req.Name)
//fmt.Printf("DEBUG Move Request - Hash: %s\n", req.Hash)
//fmt.Printf("DEBUG Move Request - OriginalHash: %s\n", req.OriginalHash)
//fmt.Printf("DEBUG Move Request - ParentLinkID: %s\n", req.ParentLinkID)
//fmt.Printf("DEBUG Move Request - Name length: %d\n", len(req.Name))
//fmt.Printf("DEBUG Move Request - NameSignatureEmail: %s\n", req.NameSignatureEmail)
//fmt.Printf("DEBUG Move Request - ContentHash: %v\n", req.ContentHash)
//fmt.Printf("DEBUG Move Request - NodePassphrase length: %d\n", len(req.NodePassphrase))
//fmt.Printf("DEBUG Move Request - NodePassphraseSignature length: %d\n", len(req.NodePassphraseSignature))
//fmt.Printf("DEBUG Move Request - SrcLinkID: %s\n", linkID)View on GitHub (pinned to 843d9dc814)
Solutions
- Re-fetch the link (fresh OriginalHash) and recompute both hashes, then retry once
- If the code indicates a name conflict, auto-suffix or surface a 'name exists' error to the user
- Map and log the numeric code so 401 vs hash-mismatch vs conflict is distinguishable
- Move renames onto the official proton-go API client which decodes these codes for you
Defensive patterns
Strategy: retry
Type guard
func isRenameCodeErr(err error) (code int, ok bool) {
var n int
if _, e := fmt.Sscanf(err.Error(), "rename failed with code %d", &n); e == nil { return n, true }
return 0, false
} Try / catch
if code, ok := isRenameCodeErr(err); ok {
if isAuthCode(code) { refreshCreds(); retry() }
else if isHashMismatchCode(code) { refetchLink(); recomputeHashes(); retryOnce() }
else if isNameConflictCode(code) { newName = uniquify(newName); retry() }
} Prevention
- Re-fetch link metadata immediately before renaming to keep OriginalHash fresh
- Avoid two clients renaming the same tree concurrently
- Map Proton API codes in one place so handling stays maintainable
When it happens
Trigger: OriginalHash stale because the file was renamed by another client since the link was fetched; newHash computed with the wrong parent hash key; Name already exists in the parent (Proton enforces per-folder name-hash uniqueness); access token rejected at the API layer.
Common situations: Two clients renaming the same file concurrently; rename after the mount's link cache went stale; keyring/address-key problems producing a wrong name hash; shared-folder permission edges.
Related errors
- rename API call failed: %w
- rename failed: %s
- failed to get original hash: %w
- move operation failed with code: %d
- same-name files cannot be Rename
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/10939a64d3c47338.
Report an issue: GitHub.