{"record":{"id":"3000a6ad4782f4f4","repo":"multica-ai/multica","slug":"repo-is-configured-but-not-synced-s","errorCode":null,"errorMessage":"repo is configured but not synced: %s","messagePattern":"repo is configured but not synced: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/internal/daemon/daemon.go","lineNumber":3391,"sourceCode":"\tif !d.workspaceRepoAllowed(workspaceID, repoURL) {\n\t\treturn ErrRepoNotConfigured\n\t}\n\n\tif d.repoCache.Lookup(workspaceID, repoURL) != \"\" {\n\t\treturn nil\n\t}\n\n\td.syncWorkspaceReposContext(ctx, workspaceID, resp.Repos)\n\tif err := ctx.Err(); err != nil {\n\t\treturn context.Cause(ctx)\n\t}\n\n\tif d.repoCache.Lookup(workspaceID, repoURL) != \"\" {\n\t\treturn nil\n\t}\n\n\tif syncErr := d.workspaceLastRepoSyncErr(workspaceID); syncErr != \"\" {\n\t\treturn fmt.Errorf(\"repo is configured but not synced: %s\", syncErr)\n\t}\n\n\treturn fmt.Errorf(\"repo is configured but not synced\")\n}\n\n// DefaultTokenRenewalInterval is how often the daemon asks the server to\n// extend its PAT. The server-side threshold is 7 days of remaining lifetime;\n// polling every ~3 days gives at least two chances to renew before the\n// window closes, so a single failed call (network blip, server restart) does\n// not push the token out of the renewal window.\nconst DefaultTokenRenewalInterval = 3 * 24 * time.Hour\n\n// preflightAuth runs the two auth-sensitive startup steps in their\n// required order: a synchronous PAT renewal first, then the initial\n// workspace sync. The order matters — running tryRenewToken before any\n// other API call is what surfaces a user-actionable \"run multica login\"\n// WARN when the PAT is already revoked or expired. If we let the\n// workspace sync go first, its 401 would short-circuit Run before the","sourceCodeStart":3373,"sourceCodeEnd":3409,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/internal/daemon/daemon.go#L3373-L3409","documentation":"The repo URL is configured for the workspace and the repo list refreshed successfully, but the requested repo is not in the synced set — and the last sync attempt for the workspace recorded an error, which is appended for diagnosis. This is the informative sibling of the bare 879: it tells you WHY the sync didn't produce the repo (e.g. clone failure, auth failure to the git remote).","triggerScenarios":"Requesting a task whose repoURL is in the workspace's allow-list while the workspace's background repo sync failed — bad git credentials, unreachable git host, clone timeout, or disk full in the workspaces root.","commonSituations":"Expired git provider tokens (GitHub PAT), private repo the daemon cannot clone, git host outage, full disk, or a first sync still in flight/failed before the task arrived.","solutions":["Read the appended sync error — it names the actual git failure (auth, DNS, timeout)","Fix git credentials for the remote (e.g. refresh the GitHub PAT used by the workspace) and trigger a workspace repo re-sync","Verify the git host is reachable from the daemon host and the workspaces root has free disk","Confirm the repoURL string matches exactly what is configured (trailing .git, scheme, case)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Before dispatch, confirm the repo is present and healthy.\nif d.repoCache.Lookup(workspaceID, repoURL) == \"\" {\n    if syncErr := d.workspaceLastRepoSyncErr(workspaceID); syncErr != \"\" {\n        return fmt.Errorf(\"workspace repo sync previously failed (%s); fix credentials and re-sync before dispatching\", syncErr)\n    }\n}","typeGuard":null,"tryCatchPattern":"Parse out the appended sync error; retry the task dispatch after re-triggering the workspace sync. Do NOT retry blindly — an auth failure against the git remote is deterministic until credentials change.","preventionTips":["Keep git provider credentials for workspaces current","Alert on workspace repo sync failures so tasks don't queue behind a broken sync","Standardize repo URL forms at configuration time"],"tags":["daemon","repos","git","sync","auth"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}