iawia002/lux · error
请先购买课程,或使用Cookie登录。
Error message
请先购买课程,或使用Cookie登录。
What it means
The GeekBang article API responded successfully but with an empty VideoID and ColumnHadSub=false: the account behind the supplied cookie has not purchased this paid column, or no cookie reached the request at all. The Chinese message translates to 'Please purchase the course first, or log in with Cookie.'
Source
Thrown at extractors/geekbang/geekbang.go:113
heanders := map[string]string{"Origin": "https://time.geekbang.org", "Content-Type": "application/json", "Referer": url}
params := strings.NewReader(fmt.Sprintf(`{"id": %q}`, matches[2]))
res, err := request.Request(http.MethodPost, "https://time.geekbang.org/serv/v1/article", params, heanders)
if err != nil {
return nil, errors.WithStack(err)
}
defer res.Body.Close() // nolint
var data geekData
if err = json.NewDecoder(res.Body).Decode(&data); err != nil {
return nil, errors.WithStack(err)
}
if data.Code < 0 {
return nil, errors.New(string(data.Error))
}
if data.Data.VideoID == "" && !data.Data.ColumnHadSub {
return nil, errors.New("请先购买课程,或使用Cookie登录。")
}
// Get video license token information
params = strings.NewReader("{\"source_type\":1,\"aid\":" + matches[2] + ",\"video_id\":\"" + data.Data.VideoID + "\"}")
res, err = request.Request(http.MethodPost, "https://time.geekbang.org/serv/v3/source_auth/video_play_auth", params, heanders)
if err != nil {
return nil, errors.WithStack(err)
}
defer res.Body.Close() // nolint
var playAuth videoPlayAuth
if err = json.NewDecoder(res.Body).Decode(&playAuth); err != nil {
return nil, errors.WithStack(err)
}
if playAuth.Code < 0 {
return nil, errors.New(string(playAuth.Error))
}View on GitHub (pinned to dd00f6d258)
Solutions
- Log in with the purchasing account, export its cookie, and pass it via -c.
- Verify in a browser (same account) that the video actually plays.
- If you do own the course, re-export the cookie — stale sessions also land here.
Example fix
// before $ lux "https://time.geekbang.org/column/article/123456" // after $ lux -c cookie-purchased-account.txt "https://time.geekbang.org/column/article/123456"
Defensive patterns
Strategy: try-catch
Type guard
func isGeekbangPurchaseRequired(err error) bool {
return err != nil && strings.Contains(err.Error(), "请先购买课程")
} Try / catch
Catch and branch on the message: purchase/login prompt means credential or entitlement problems — re-authenticate with the purchasing account and retry. Do not retry with the same cookie; it cannot succeed.
Prevention
- Confirm the account owns the column before queueing its articles
- Separate free-preview and paid URLs in batch files
- Re-export cookies whenever entitlements change
When it happens
Trigger: Running without -c; a cookie belonging to an account without the subscription; free-preview articles whose full video requires purchase.
Common situations: Assuming an article link is free; stale exported cookies; team members sharing links but not entitlements.
Related errors
AI-assisted analysis of iawia002/lux@dd00f6d258 (2026-08-15).
Data as JSON: /api/errors/cd94c516dc0d20a6.
Report an issue: GitHub.