{"record":{"id":"49bd42e1a336d529","repo":"Molunerfinn/PicGo","slug":"failed-to-save-provider-config","errorCode":null,"errorMessage":"Failed to save provider config","messagePattern":"Failed to save provider config","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/renderer/adapters/providers.ts","lineNumber":55,"sourceCode":"    const result = await invokeRPC<IUploaderConfigItem>(IRPCActionType.DELETE_PICBED_CONFIG, type, configName)\n    if (!result.success) {\n      throw new Error(result.error || 'Failed to delete provider config')\n    }\n\n    return result.data\n  },\n  async copyProviderConfig (type: string, configName: string, newConfigName: string) {\n    const result = await invokeRPC<IUploaderConfigItem>(IRPCActionType.COPY_UPLOADER_CONFIG, type, configName, newConfigName)\n    if (!result.success) {\n      throw new Error(result.error || 'Failed to copy provider config')\n    }\n\n    return result.data\n  },\n  async saveProviderConfig (type: string, configId: string, values: IStringKeyMap) {\n    const result = await invokeRPC<boolean>(IRPCActionType.UPDATE_UPLOADER_CONFIG, type, configId, values)\n    if (!result.success) {\n      throw new Error(result.error || 'Failed to save provider config')\n    }\n\n    if (result.data !== true) {\n      throw new Error('Failed to save provider config')\n    }\n  },\n  getProviderSchema (type: string): Promise<ProviderSchemaResult> {\n    return new Promise((resolve, reject) => {\n      const cleanup = ipc.once(GET_PICBED_CONFIG, (config: IPicGoPluginConfig[], name: string) => {\n        resolve({ config, name })\n      })\n\n      try {\n        sendToMain(GET_PICBED_CONFIG, type)\n      } catch (error) {\n        cleanup()\n        reject(error)\n      }","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/Molunerfinn/PicGo/blob/07ec7068a5512344da093d49a8408fa63ba3421e/src/renderer/adapters/providers.ts#L37-L73","documentation":"saveProviderConfig sends IRPCActionType.UPDATE_UPLOADER_CONFIG and throws in two cases: the RPC result reports failure, or result.data !== true (the handler did not confirm the write). The main handler (src/main/events/rpc/routes/config.ts:97) throws TIPS_UPLOADER_CONFIG_NAME_EMPTY when updating (configId set) without _configName, and TIPS_UPLOADER_CONFIG_NOT_FOUND when the configId does not match any existing config, then renames and creates/updates via picgo.uploaderConfig.","triggerScenarios":"Calling saveProviderConfig(type, configId, values) where values._configName is missing/empty while updating an existing config; configId refers to a config deleted in another window; main process write to the PicGo config fails so success=false or data!==true.","commonSituations":"Saving a renamed config whose name field was cleared in the form; concurrent deletion making the configId stale; corrupted config file preventing createOrUpdate; renderer form submitting values without _configName attached.","solutions":["Ensure values includes a non-empty _configName string when configId is provided","Refresh the config list and verify the configId still exists before saving","Check result.error / main-process logs for TIPS_UPLOADER_CONFIG_NAME_EMPTY or TIPS_UPLOADER_CONFIG_NOT_FOUND","If the config was deleted elsewhere, recreate it (create flow, empty configId) instead of updating","Verify the PicGo config file is writable and not corrupted"],"exampleFix":"// before\nawait saveProviderConfig(type, configId, values)\n// after\nif (configId && !values._configName) throw new Error('config name is required when updating')\nconst { configList } = await getProviderConfigList(type)\nif (!configList.some(c => c._id === configId)) throw new Error('config no longer exists')\nawait saveProviderConfig(type, configId, values)","handlingStrategy":"validation","validationCode":"if (configId && (typeof values._configName !== 'string' || !values._configName.trim())) {\n  throw new Error('config name is required when updating an existing config')\n}","typeGuard":"function isSavable(configId: string, values: IStringKeyMap): boolean {\n  return !configId || (typeof values._configName === 'string' && values._configName.trim().length > 0)\n}","tryCatchPattern":"try {\n  await saveProviderConfig(type, configId, values)\n} catch (e) {\n  logger.error('[picbed] save failed', e)\n  showNotification((e as Error).message || $T('TIPS_SAVE_CONFIG_FAILED'))\n  // keep the form open so the user does not lose entered values\n}","preventionTips":["Always attach _configName to the values object when editing an existing config (configId set)","Require non-empty config names in the form before enabling Save","Refresh the config list before save to confirm the configId still exists","Keep the form data intact on failure and let the user correct and retry","Verify the config file location is writable (no permission/AV lock)"],"tags":["ipc","rpc","config","validation"],"backgroundTag":"rpc-failed-result","analyzedSha":"07ec7068a5512344da093d49a8408fa63ba3421e","analyzedAt":"2026-08-30T01:45:22.289Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}