vxcontrol/pentagi · error

failed to copy resource: %w

Error message

failed to copy resource: %w

What it means

copyFileResource inserts the new UserResource row for the copied file inside the copy transaction. This error wraps the GORM/Postgres failure of that INSERT, meaning the database rejected the copy record (not the file itself). The whole copy transaction is rolled back by the caller.

Source

Thrown at backend/pkg/server/services/resources.go:1544

		if err := tx.Delete(&dest).Error; err != nil {
			return result, fmt.Errorf("failed to delete destination for overwrite: %w", err)
		}
		result.Deleted = append(result.Deleted, convertResource(dest))
		if dest.Hash != "" {
			result.OrphanHashes = append(result.OrphanHashes, dest.Hash)
		}
	}

	newRec := models.UserResource{
		UserID: uid,
		Hash:   src.Hash,
		Name:   path.Base(targetPath),
		Path:   targetPath,
		Size:   src.Size,
		IsDir:  false,
	}
	if err := tx.Create(&newRec).Error; err != nil {
		return result, fmt.Errorf("failed to copy resource: %w", err)
	}

	entry := convertResource(newRec)
	if exists {
		result.Updated = append(result.Updated, entry)
	} else {
		result.Added = append(result.Added, entry)
	}
	return result, nil
}

func (s *ResourceService) copyDirResource(
	tx *gorm.DB,
	uid uint64,
	srcPath, dstPath string,
	force bool,
) (copyResourceResult, error) {
	result := copyResourceResult{}

View on GitHub (pinned to ea665308ba)

Solutions

  1. Retry the request; if it is a conflict, list the destination first and either pick a new destination path or pass force=true
  2. Check the DB schema/migrations for the user_resources unique index and column sizes
  3. Verify DB connectivity/health (logs will show the wrapped %w cause)
  4. If caused by concurrent writes, serialize copy operations per user or add retry-on-serialization logic

Example fix

// before
res, err := svc.CopyResource(uid, src, dst, false)
// after
if _, exists := checkDestExists(uid, dst); exists && !allowOverwrite {
    return errors.New("destination exists; pass force to overwrite")
}
res, err := svc.CopyResource(uid, src, dst, allowOverwrite)
Defensive patterns

Strategy: retry

Validate before calling

exists, err := resourceExists(uid, dstPath)
if err != nil { return err }
if exists && !force { return errConflict }

Try / catch

res, err := svc.CopyResource(uid, src, dst, force)
if err != nil {
    var conflict error
    if errors.As(err, &conflict) && errors.Is(conflict, errResourceConflict) {
        // handle overwrite policy
    } else {
        log.WithError(err).Error("copy failed (db insert)") // inspect %w cause
    }
}

Prevention

When it happens

Trigger: DELETE/constraint failure on tx.Create while copying a file: e.g. a unique (user_id, path) collision from a concurrent writer, a NOT NULL/length violation on path or name, or a dead/broken DB connection during the copy API call.

Common situations: Two copy/move requests racing to create the same destination path without force; path exceeding the DB column length after a deep destination directory; DB connection dropped mid-request.

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/ea7ed12eaec560a1. Report an issue: GitHub.