mihomo-party-org/clash-party · warning

[ProfileUpdater] Failed to update ${logLabel}:

Error message

[ProfileUpdater] Failed to update ${logLabel}:

What it means

updateTask is the scheduled callback created by addProfileUpdater/scheduleProfileUpdate; it calls updateProfile(itemId) and swallows any rejection, logging this warning with a human label (logLabel). The scheduled update for a remote or plugin profile failed, but the failure is contained so the scheduler keeps running.

Source

Thrown at src/main/core/profileUpdater.ts:66

  }
}

async function auditPluginProfileVault(item: IProfileItem): Promise<void> {
  if (item.type !== 'plugin' || !item.pluginId) return
  try {
    const { auditPluginVault } = await import('../resolve/plugin')
    await auditPluginVault(item.pluginId)
  } catch (e) {
    await logger.warn(`[ProfileUpdater] Failed to audit plugin vault ${item.pluginId}:`, e)
  }
}

function updateTask(itemId: string, logLabel: string): () => Promise<void> {
  return async () => {
    try {
      await updateProfile(itemId)
    } catch (e) {
      await logger.warn(`[ProfileUpdater] Failed to update ${logLabel}:`, e)
    }
  }
}

function scheduleProfileUpdate(item: IProfileItem): void {
  if ((item.type !== 'remote' && item.type !== 'plugin') || !item.autoUpdate || !item.interval)
    return

  const itemId = item.id
  const logLabel = `profile ${itemId}`
  const delayMs = intervalDelayMs(item.interval)
  if (delayMs) {
    intervalPool[itemId] = setInterval(updateTask(itemId, logLabel), delayMs)
    return
  }

  if (typeof item.interval !== 'string') return

View on GitHub (pinned to 911e090537)

Solutions

  1. Check the logged error `e` for HTTP status or network cause and test the subscription URL manually (curl).
  2. Retry the update manually from the UI once connectivity is restored.
  3. Fix the subscription source (renew URL/auth) or increase interval; verify updateProfile's validation rules accept the payload.

Example fix

// before
await updateProfile(itemId)
// after
try {
  await updateProfile(itemId)
} catch (e) {
  if (isNetworkError(e)) scheduleRetry(itemId, 60_000)
  else logger.warn(`Non-retryable profile update failure:`, e)
}
Defensive patterns

Strategy: retry

Validate before calling

const res = await fetch(item.url, { method: 'HEAD' }).catch(() => null)
if (!res || !res.ok) {
  logger.warn(`subscription unreachable for ${item.id}; deferring update`)
  return
}

Try / catch

try {
  await updateProfile(itemId)
} catch (e) {
  logger.warn(`[ProfileUpdater] Failed to update ${logLabel}:`, e)
  scheduleRetryWithBackoff(itemId)
}

Prevention

When it happens

Trigger: The interval timer fires for a profile with autoUpdate enabled and updateProfile rejects: network failure reaching the remote URL, HTTP non-2xx, invalid downloaded content rejected by validation, or file-system write errors.

Common situations: Offline / captive portal at update time; subscription URL expired or returning 401/403; proxy not yet ready when the timer fires; DNS failure for the subscription host.

Related errors


AI-assisted analysis of mihomo-party-org/clash-party@911e090537 (2026-08-30). Data as JSON: /api/errors/d60f503bc27df6e3. Report an issue: GitHub.