{"record":{"id":"d6f6175373cf10e5","repo":"pot-app/pot-desktop","slug":"can-not-find-avatar-or-name-json-stringify-resu","errorCode":null,"errorMessage":"Can not find avatar or name: ${JSON.stringify(result)}","messagePattern":"Can not find avatar or name: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/window/Config/pages/Backup/utils/aliyun.jsx","lineNumber":151,"sourceCode":"            throw new Error(result['message']);\n        } else {\n            throw new Error(`Get Status Error: ${JSON.stringify(result)}`);\n        }\n    }\n}\n\nexport async function userInfo(token) {\n    const res = await fetch('https://openapi.alipan.com/oauth/users/info', {\n        headers: {\n            Authorization: `Bearer ${token}`,\n        },\n    });\n    if (res.ok) {\n        const result = res.data;\n        if (result.hasOwnProperty('avatar') && result.hasOwnProperty('name')) {\n            return { avatar: result['avatar'], name: result['name'] };\n        } else {\n            throw new Error(`Can not find avatar or name: ${JSON.stringify(result)}`);\n        }\n    } else {\n        const result = res.data;\n        if (result['message']) {\n            throw new Error(result['message']);\n        } else {\n            throw new Error(`Get UserInfo Error: ${JSON.stringify(result)}`);\n        }\n    }\n}\n\nexport async function accessToken(code) {\n    const res = await fetch('https://pot-app.com/api/ali_access_token', {\n        method: 'POST',\n        body: Body.json({\n            code,\n            refresh_token: '',\n        }),","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/pot-app/pot-desktop/blob/594d32ede96acd106b0256deaa8bb440ffcdff40/src/window/Config/pages/Backup/utils/aliyun.jsx#L133-L169","documentation":"The userInfo() helper calls https://openapi.alipan.com/oauth/users/info with the access token and expects `avatar` and `name` in a 200 response. If either property is missing, it throws `Can not find avatar or name: <body JSON>`, i.e. the token was accepted but the profile payload didn't match the expected shape.","triggerScenarios":"Calling userInfo(token) with an HTTP 200 whose res.data lacks `avatar` or `name` — e.g. the token was issued with insufficient scopes (missing user:base), or the users/info response schema changed.","commonSituations":"Authorizing with scopes that exclude user:base so the API omits profile fields; using a partially-valid token from a different account type; Alipan renaming fields in the OAuth users/info endpoint.","solutions":["Check the JSON dump for which field is missing — if both, the token is likely invalid/limited.","Re-authorize via the QR flow ensuring the `user:base` scope is requested (as qrcode() does).","Verify the token is a fresh Alipan OAuth access token, not a refresh token or app token.","Check for Alipan API schema changes and update the field checks."],"exampleFix":"// before\nif (result.hasOwnProperty('avatar') && result.hasOwnProperty('name')) {\n    return { avatar: result['avatar'], name: result['name'] };\n}\n// after\nconst avatar = result?.avatar ?? '';\nconst name = result?.name;\nif (typeof name === 'string') {\n    return { avatar, name }; // tolerate missing avatar, require only name\n}","handlingStrategy":"validation","validationCode":"// validate token scope/shape before calling userInfo\nfunction looksLikeAccessToken(token) {\n  return typeof token === 'string' && token.split('.').length >= 2 && token.length > 20;\n}\n// ensure the QR flow requested the 'user:base' scope before exchanging for a token","typeGuard":"function hasProfileFields(r) {\n  return r && typeof r === 'object' && typeof r.name === 'string' && ('avatar' in r);\n}","tryCatchPattern":"try {\n  const { avatar, name } = await userInfo(token);\n} catch (e) {\n  if (String(e.message).startsWith('Can not find avatar or name')) {\n    // token accepted but profile incomplete — likely missing user:base scope\n    await reAuthorizeWithBaseScope();\n  } else {\n    showError(e.message);\n  }\n}","preventionTips":["Always request the `user:base` scope in the QR authorization (as qrcode() does)","Verify the access token is a fresh Alipan OAuth token before calling userInfo","Degrade gracefully: require only `name`, tolerate a missing avatar","Test the users/info response shape against the current Alipan API version"],"tags":["oauth","token-scope","response-shape","alipan"],"backgroundTag":"api-response-missing-field","analyzedSha":"594d32ede96acd106b0256deaa8bb440ffcdff40","analyzedAt":"2026-09-02T18:12:21.811Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}