fish2018/pansou · error
入口脚本未找到搜索接口标识
Error message
入口脚本未找到搜索接口标识
What it means
After locating the search route in the entry bundle, the plugin looks backwards up to 2048 bytes for hash-like identifiers (hashPattern) that encode the server function ID. If none are found it returns this error, because the server function ID needed to call the search API could not be extracted.
Solutions
- Inspect the bundle around the route string and update hashPattern to the new identifier format.
- Widen the 2048-byte window (or search the whole bundle) if the hash is simply farther from the route literal.
- If the ID moved to a manifest/build-metadata file, fetch and parse that file instead.
- Upgrade the plugin to a version compatible with the current site build.
Example fix
// before windowStart := max(0, routeIndex-2048) hashes := hashPattern.FindAll(assetBody[windowStart:routeIndex], -1) // after windowStart := max(0, routeIndex-16384) hashes := hashPattern.FindAll(assetBody[windowStart:routeIndex], -1)
Defensive patterns
Strategy: validation
Validate before calling
window := assetBody[max(0, routeIndex-16384):routeIndex]
if len(hashPattern.FindAll(window, -1)) == 0 {
log.Printf("no function-ID hash near route; pattern needs update")
} Type guard
func hasFunctionIDHash(body []byte, routeIndex int) bool {
window := body[max(0, routeIndex-2048):routeIndex]
return len(hashPattern.FindAll(window, -1)) > 0
} Try / catch
funcID, err := discoverServerFunctionID(ctx, req)
if err != nil && strings.Contains(err.Error(), "入口脚本未找到搜索接口标识") {
log.Printf("hash pattern outdated: %v", err)
return nil, errSkipPlugin
} Prevention
- Widen the lookahead window defensively rather than assuming the hash sits within 2KB.
- Re-verify hashPattern against a freshly downloaded bundle whenever the site ships a new build.
- Cache the discovered function ID with a TTL and refresh silently on failure.
When it happens
Trigger: hashPattern.FindAll over the 2048-byte window before "/s/$query" yields zero matches: the bundle layout changed so the hash is farther away, in a different format, or generated at runtime.
Common situations: Bundler upgrade changed chunk hashing/format or moved the function ID reference beyond the 2048-byte window; the ID is now fetched from a separate manifest file; minification altered identifier shape.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/275cf5379ed019d8.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/xiaokupan/xiaokupan.go:258
assetReq, err := http.NewRequestWithContext(ctx, http.MethodGet, strings.TrimRight(p.baseURL, "/")+assetPath, nil)
if err != nil {
return "", err
}
assetReq.Header.Set("User-Agent", req.Header.Get("User-Agent"))
assetReq.Header.Set("Referer", homeURL)
assetBody, err := doLimitedRequest(client, assetReq, maxDiscoveryBodySize)
if err != nil {
return "", fmt.Errorf("读取入口脚本失败: %w", err)
}
routeIndex := strings.Index(string(assetBody), "/s/$query")
if routeIndex < 0 {
return "", fmt.Errorf("入口脚本未找到搜索路由")
}
windowStart := max(0, routeIndex-2048)
hashes := hashPattern.FindAll(assetBody[windowStart:routeIndex], -1)
if len(hashes) == 0 {
return "", fmt.Errorf("入口脚本未找到搜索接口标识")
}
return string(hashes[len(hashes)-1]), nil
}
func parseSearchResponse(body []byte) ([]model.SearchResult, error) {
var root serovalNode
if err := stdjson.Unmarshal(body, &root); err != nil {
return nil, fmt.Errorf("解析 Seroval 响应失败: %w", err)
}
decoder := newSerovalDecoder(&root)
resultNode := decoder.objectValue(&root, "result")
searchResultsNode := decoder.objectValue(resultNode, "searchResults")
mergedNode := decoder.objectValue(searchResultsNode, "merged_by_type")
mergedNode = decoder.resolve(mergedNode)
if mergedNode == nil || mergedNode.Props == nil {
return nil, fmt.Errorf("响应缺少 merged_by_type")
}
View on GitHub (pinned to beaa561337)