vxcontrol/pentagi · error
failed to move resource %q: %w
Error message
failed to move resource %q: %w
What it means
updateMovedResource rewrites a user resource row's path/name/updated_at inside a DB transaction during a move. If the GORM Updates call fails (connection issue, constraint violation, deadlock, row lock), the move is aborted and this wrapped error carries the original path and the underlying DB error. It propagates up to moveFileResource / moveDirResourceToAbsentDestination / moveDirResourceMerge and the transaction is rolled back by the caller.
Source
Thrown at backend/pkg/server/services/resources.go:1176
}
func resourcesByPath(recs []models.UserResource) map[string]models.UserResource {
byPath := make(map[string]models.UserResource, len(recs))
for _, rec := range recs {
byPath[rec.Path] = rec
}
return byPath
}
func updateMovedResource(tx *gorm.DB, rec models.UserResource, newPath string, now time.Time) (models.UserResource, error) {
if err := tx.Model(&models.UserResource{}).
Where("id = ?", rec.ID).
Updates(map[string]interface{}{
"path": newPath,
"name": path.Base(newPath),
"updated_at": now,
}).Error; err != nil {
return models.UserResource{}, fmt.Errorf("failed to move resource %q: %w", rec.Path, err)
}
rec.Path = newPath
rec.Name = path.Base(newPath)
rec.UpdatedAt = now
return rec, nil
}
// ---- POST /resources/copy --------------------------------------------------
// CopyResource copies one or more resource files / directories to a new path.
//
// Single-source behaviour (exactly one unique source after dedup):
//
// Destination is the exact target path, inheriting existing trailing-slash
// and existing-directory semantics (unchanged from original behaviour).
//
// Multi-source behaviour (two or more unique sources after dedup):
//View on GitHub (pinned to ea665308ba)
Solutions
- Check the wrapped underlying DB error (errors.Unwrap / log) to identify whether it is a unique violation, deadlock, or connectivity problem.
- Retry the move once; deadlocks and transient connection errors are usually retryable.
- Pre-check that no resource already exists at newPath (findResourceByPath) or delete/archive the conflicting destination first.
- Verify DB health: connection pool limits, disk space, and that migrations ran cleanly.
Example fix
// before
updated, err := updateMovedResource(tx, entry, newPath, now)
if err != nil { return result, err }
// after
updated, err := updateMovedResource(tx, entry, newPath, now)
if err != nil {
tx.Rollback()
if errors.Is(err, syscall.ECONNRESET) || isDeadlock(err) { /* retry once */ }
return result, err
} Defensive patterns
Strategy: try-catch
Validate before calling
var existing models.UserResource
err := db.Where("user_id = ? AND path = ?", uid, newPath).First(&existing).Error
if err == nil { return errors.New("destination path already exists") } Type guard
func isUniqueViolation(err error) bool {
var pgErr *pgconn.PgError
return errors.As(err, &pgErr) && pgErr.Code == "23505"
} Try / catch
updated, err := updateMovedResource(tx, rec, newPath, now)
if err != nil {
tx.Rollback()
if isUniqueViolation(err) || isDeadlock(err) { /* retry or surface 409 */ }
return fmt.Errorf("move %q failed: %w", rec.Path, err)
} Prevention
- Always check destination availability before moving.
- Run moves inside short transactions to reduce deadlock windows.
- Monitor DB logs for deadlocks and unique violations on user_resources.
- Retry transient DB errors with exponential backoff.
When it happens
Trigger: Any move (REST move endpoint) whose UPDATE statement fails: database connection loss or timeout mid-transaction, a unique-index violation on (user_id, path) if another row already holds newPath, a deadlock with a concurrent write, or the DB being read-only / out of disk.
Common situations: Two users (or two browser tabs) racing to move resources to the same destination path; PostgreSQL restart or connection-pool exhaustion during a large directory move; a unique constraint on path added by a migration while legacy duplicate rows exist.
Related errors
- failed to copy resource %q: %w
- failed to create resource directory %q: %w
- failed to fetch resources: %w
- failed to delete destination for overwrite: %w
- failed to delete merged source directory %q: %w
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/f79dec81bb8da885.
Report an issue: GitHub.