{"record":{"id":"b7da5974e36ec686","repo":"yikart/AiToEarn","slug":"plugin-proxy-request-unavailable","errorCode":null,"errorMessage":"PLUGIN_PROXY_REQUEST_UNAVAILABLE","messagePattern":"PLUGIN_PROXY_REQUEST_UNAVAILABLE","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"project/aitoearn-web/src/store/plugin/request.ts","lineNumber":13,"sourceCode":"/**\n * 插件通用代理请求封装\n */\n\nimport type { PluginProxyRequestParams, PluginProxyResponse } from './types/baseTypes'\n\nconst PLUGIN_PROXY_REQUEST_UNAVAILABLE = 'PLUGIN_PROXY_REQUEST_UNAVAILABLE'\n\nfunction getPluginProxyMethod() {\n  const plugin = typeof window !== 'undefined' ? window.AIToEarnPlugin : undefined\n\n  if (!plugin?.proxyRequest) {\n    throw new Error(PLUGIN_PROXY_REQUEST_UNAVAILABLE)\n  }\n\n  return plugin.proxyRequest.bind(plugin)\n}\n\nexport async function proxyRequest(params: PluginProxyRequestParams): Promise<PluginProxyResponse> {\n  return getPluginProxyMethod()(params)\n}\n","sourceCodeStart":1,"sourceCodeEnd":22,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-web/src/store/plugin/request.ts#L1-L22","documentation":"proxyRequest resolves the extension's proxyRequest method via getPluginProxyMethod() and throws the sentinel Error 'PLUGIN_PROXY_REQUEST_UNAVAILABLE' when window.AIToEarnPlugin or its proxyRequest function is absent. The plugin proxy is the only channel for cross-origin requests the extension performs on behalf of the page, so without it any proxied call cannot proceed.","triggerScenarios":"Calling proxyRequest(params) (or anything built on it) in an environment where window.AIToEarnPlugin is undefined, or the plugin object exists but does not expose proxyRequest (old extension version predating the API).","commonSituations":"Extension not installed/disabled; page loaded before the extension content script ran; extension is an older build lacking proxyRequest; code path executed during SSR where window is undefined.","solutions":["Install/update the Aitoearn extension to a version exposing proxyRequest, then reload the page.","Guard calls: check `window.AIToEarnPlugin?.proxyRequest` before invoking proxyRequest and fall back to a direct fetch or an install prompt.","Catch the sentinel error by comparing err.message === 'PLUGIN_PROXY_REQUEST_UNAVAILABLE' and route to plugin-setup UX.","Avoid calling proxyRequest in non-browser contexts; add a typeof window check at the call site."],"exampleFix":"// before\nconst res = await proxyRequest({ url, method: 'GET' })\n\n// after\nif (typeof window === 'undefined' || !window.AIToEarnPlugin?.proxyRequest) {\n  return fallbackDirectRequest({ url, method: 'GET' })\n}\nconst res = await proxyRequest({ url, method: 'GET' })","handlingStrategy":"fallback","validationCode":"export function canProxy(): boolean {\n  return typeof window !== 'undefined' && typeof window.AIToEarnPlugin?.proxyRequest === 'function'\n}\nif (!canProxy()) return fallbackDirectRequest(params)","typeGuard":"function hasProxyRequest(p: unknown): p is { proxyRequest: (params: PluginProxyRequestParams) => Promise<PluginProxyResponse> } {\n  return !!p && typeof (p as any).proxyRequest === 'function'\n}","tryCatchPattern":"try {\n  return await proxyRequest(params)\n}\ncatch (e) {\n  if (e.message === 'PLUGIN_PROXY_REQUEST_UNAVAILABLE')\n    return fallbackDirectRequest(params)\n  throw e\n}","preventionTips":["Feature-detect window.AIToEarnPlugin?.proxyRequest before any proxied call","Keep the extension updated — older builds may lack proxyRequest","Never invoke proxyRequest during SSR; gate on typeof window","Maintain a documented fallback path (direct fetch) for no-plugin environments"],"tags":["browser-extension","plugin","proxy-request","fallback"],"backgroundTag":"plugin-api-unavailable","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}