Starred repos get re-duplicated on every sync (repo, repo-owner, repo-owner-1, ...)
What happens
A starred repo gets mirrored into a brand new Gitea repo on every scheduled sync, with an incrementing name. One starred source ended up as five separate repos, all mirroring the same upstream:
The app keeps a single DB row and just repoints mirrored_location at the newest copy, so the older ones become orphans. It happened to more than one starred repo, so it isn't repo-specific.
AUTO_MIRROR_STARRED=true with scheduled sync, metadata mirroring enabled
Why
The scheduled sync calls mirrorGithubRepoToGitea directly (scheduler-service.ts:269). For a starred repo it picks the destination name via generateUniqueRepoName (gitea.ts:1185) before any reuse check. That function's isNameTaken only asks "does a repo with this name exist", never "is it already a mirror of this same source". So it treats the repo's own previous mirror as a collision and moves on to the next free suffix, creating a new repo each run. The "already mirrored" reuse check right after (gitea.ts:606) runs against the freshly generated unique name, so it never matches.
It compounds with the scheduler's selection (scheduler-service.ts:214): only repos in status imported, pending, or failed get re-mirrored. If a sync never finishes (e.g. metadata mirroring of a huge repo times out), the repo never reaches mirrored, so every cycle re-runs the create path and adds another duplicate.
Expected
Reuse the existing mirror instead of creating a new one. If repository.mirroredLocation is set, or a repo at the candidate name is already a mirror of the same source, sync that one. Only allocate a new name for a genuine collision with a different source.
Originally created by @Quadrubo on GitHub (Jun 7, 2026).
Original GitHub issue: https://github.com/RayLabsHQ/gitea-mirror/issues/315
Originally assigned to: @arunavo4 on GitHub.
## Starred repos get re-duplicated on every sync (`repo`, `repo-owner`, `repo-owner-1`, ...)
### What happens
A starred repo gets mirrored into a brand new Gitea repo on every scheduled sync, with an incrementing name. One starred source ended up as five separate repos, all mirroring the same upstream:
```
starred/immich
starred/immich-immich-app
starred/immich-immich-app-1
starred/immich-immich-app-2
```
The app keeps a single DB row and just repoints `mirrored_location` at the newest copy, so the older ones become orphans. It happened to more than one starred repo, so it isn't repo-specific.
### Version / setup
- v3.17.0
- Starred repos, `dedicated-org` mode (org `starred`), default `suffix` duplicate strategy
- `AUTO_MIRROR_STARRED=true` with scheduled sync, metadata mirroring enabled
### Why
The scheduled sync calls `mirrorGithubRepoToGitea` directly (`scheduler-service.ts:269`). For a starred repo it picks the destination name via `generateUniqueRepoName` (`gitea.ts:1185`) before any reuse check. That function's `isNameTaken` only asks "does a repo with this name exist", never "is it already a mirror of this same source". So it treats the repo's own previous mirror as a collision and moves on to the next free suffix, creating a new repo each run. The "already mirrored" reuse check right after (`gitea.ts:606`) runs against the freshly generated unique name, so it never matches.
It compounds with the scheduler's selection (`scheduler-service.ts:214`): only repos in status `imported`, `pending`, or `failed` get re-mirrored. If a sync never finishes (e.g. metadata mirroring of a huge repo times out), the repo never reaches `mirrored`, so every cycle re-runs the create path and adds another duplicate.
### Expected
Reuse the existing mirror instead of creating a new one. If `repository.mirroredLocation` is set, or a repo at the candidate name is already a mirror of the same source, sync that one. Only allocate a new name for a genuine collision with a different source.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Originally created by @Quadrubo on GitHub (Jun 7, 2026).
Original GitHub issue: https://github.com/RayLabsHQ/gitea-mirror/issues/315
Originally assigned to: @arunavo4 on GitHub.
Starred repos get re-duplicated on every sync (
repo,repo-owner,repo-owner-1, ...)What happens
A starred repo gets mirrored into a brand new Gitea repo on every scheduled sync, with an incrementing name. One starred source ended up as five separate repos, all mirroring the same upstream:
The app keeps a single DB row and just repoints
mirrored_locationat the newest copy, so the older ones become orphans. It happened to more than one starred repo, so it isn't repo-specific.Version / setup
dedicated-orgmode (orgstarred), defaultsuffixduplicate strategyAUTO_MIRROR_STARRED=truewith scheduled sync, metadata mirroring enabledWhy
The scheduled sync calls
mirrorGithubRepoToGiteadirectly (scheduler-service.ts:269). For a starred repo it picks the destination name viagenerateUniqueRepoName(gitea.ts:1185) before any reuse check. That function'sisNameTakenonly asks "does a repo with this name exist", never "is it already a mirror of this same source". So it treats the repo's own previous mirror as a collision and moves on to the next free suffix, creating a new repo each run. The "already mirrored" reuse check right after (gitea.ts:606) runs against the freshly generated unique name, so it never matches.It compounds with the scheduler's selection (
scheduler-service.ts:214): only repos in statusimported,pending, orfailedget re-mirrored. If a sync never finishes (e.g. metadata mirroring of a huge repo times out), the repo never reachesmirrored, so every cycle re-runs the create path and adds another duplicate.Expected
Reuse the existing mirror instead of creating a new one. If
repository.mirroredLocationis set, or a repo at the candidate name is already a mirror of the same source, sync that one. Only allocate a new name for a genuine collision with a different source.@arunavo4 commented on GitHub (Jun 13, 2026):
@Quadrubo try the latest version