{"record":{"id":"7ecbd0ac0c76df8d","repo":"fish2018/pansou","slug":"token","errorCode":null,"errorMessage":"盘链 token 为空","messagePattern":"盘链 token 为空","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"plugin/panlian/panlian.go","lineNumber":910,"sourceCode":"\t\t}()\n\t}\n\twg.Wait()\n\tclose(resultCh)\n\n\tfor result := range resultCh {\n\t\tgroup, ok := groups[result.groupKey]\n\t\tif !ok || result.index < 0 || result.index >= len(group.Links) {\n\t\t\tcontinue\n\t\t}\n\t\tgroup.Links[result.index].URL = result.url\n\t\tgroups[result.groupKey] = group\n\t}\n}\n\nfunc (p *PanlianPlugin) resolvePanToken(client *http.Client, cookie string, token string) (string, error) {\n\ttoken = strings.TrimSpace(token)\n\tif token == \"\" {\n\t\treturn \"\", fmt.Errorf(\"盘链 token 为空\")\n\t}\n\tif isRealPanURL(token) {\n\t\treturn token, nil\n\t}\n\tif client == nil {\n\t\tclient = p.GetClient()\n\t}\n\tif client == nil {\n\t\tclient = &http.Client{Timeout: RequestTimeout}\n\t}\n\n\tpayload, err := json.Marshal(map[string]string{\"token\": token})\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tctx, cancel := context.WithTimeout(context.Background(), RequestTimeout)\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, DefaultBaseURL+\"/api/resolve_token.php\", bytes.NewReader(payload))\n\tif err == nil {","sourceCodeStart":892,"sourceCodeEnd":928,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/panlian/panlian.go#L892-L928","documentation":"resolvePanToken rejects an empty token with '盘链 token 为空' ('panlian token is empty'). A pan group entry contained no usable token/URL after trimming, so there is nothing to resolve into a real pan link.","triggerScenarios":"resolvePanLinkTokens iterates groups and encounters a PanGroup item whose token field is empty or whitespace-only; upstream returned a group with missing token data.","commonSituations":"panlian listing includes placeholder/empty entries for items whose links were removed; JSON schema drift leaving token fields unset; scraping a deleted resource.","solutions":["Skip entries with empty tokens in resolvePanLinkTokens instead of failing the whole resolution.","Log and drop malformed groups; verify the upstream response for that item.","Update the PanGroup struct/parsing if upstream renamed the token field.","Report the resource as having no links rather than surfacing an error to the user."],"exampleFix":"// before\nresolved, err := p.resolvePanToken(client, cookie, token)\nif err != nil { return err }\n// after\nif strings.TrimSpace(token) == \"\" { continue } // skip empty entries\nresolved, err := p.resolvePanToken(client, cookie, token)","handlingStrategy":"validation","validationCode":"// filter entries before resolution\nusable := groups[:0]\nfor _, g := range groups {\n    if strings.TrimSpace(g.Token) != \"\" {\n        usable = append(usable, g)\n    }\n}","typeGuard":"func hasToken(g PanGroup) bool {\n    return strings.TrimSpace(g.Token) != \"\"\n}","tryCatchPattern":"url, err := plugin.ResolveToken(ctx, token)\nif err != nil && strings.Contains(err.Error(), \"盘链 token 为空\") {\n    continue // skip empty entry, keep processing other groups\n}","preventionTips":["Always TrimSpace token fields parsed from upstream JSON.","Skip-and-log empty entries instead of failing the whole batch.","Validate PanGroup JSON schema after upstream updates.","Treat missing tokens as 'no link available', not a hard error."],"tags":["validation","empty-value","token","upstream-data"],"backgroundTag":"empty-required-field","analyzedSha":"beaa56133755a548ebc51b090b3816e2ae044aa6","analyzedAt":"2026-09-07T00:31:18.025Z","contentChangedAt":"2026-09-07T00:31:18.025Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}