{"record":{"id":"8083786751902b95","repo":"iawia002/lux","slug":"string-data-error","errorCode":null,"errorMessage":"string(data.Error)","messagePattern":"string\\(data\\.Error\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"extractors/geekbang/geekbang.go","lineNumber":109,"sourceCode":"\t\treturn nil, errors.WithStack(extractors.ErrURLParseFailed)\n\t}\n\n\t// Get video information\n\theanders := map[string]string{\"Origin\": \"https://time.geekbang.org\", \"Content-Type\": \"application/json\", \"Referer\": url}\n\tparams := strings.NewReader(fmt.Sprintf(`{\"id\": %q}`, matches[2]))\n\tres, err := request.Request(http.MethodPost, \"https://time.geekbang.org/serv/v1/article\", params, heanders)\n\tif err != nil {\n\t\treturn nil, errors.WithStack(err)\n\t}\n\tdefer res.Body.Close() // nolint\n\n\tvar data geekData\n\tif err = json.NewDecoder(res.Body).Decode(&data); err != nil {\n\t\treturn nil, errors.WithStack(err)\n\t}\n\n\tif data.Code < 0 {\n\t\treturn nil, errors.New(string(data.Error))\n\t}\n\n\tif data.Data.VideoID == \"\" && !data.Data.ColumnHadSub {\n\t\treturn nil, errors.New(\"请先购买课程，或使用Cookie登录。\")\n\t}\n\n\t// Get video license token information\n\tparams = strings.NewReader(\"{\\\"source_type\\\":1,\\\"aid\\\":\" + matches[2] + \",\\\"video_id\\\":\\\"\" + data.Data.VideoID + \"\\\"}\")\n\tres, err = request.Request(http.MethodPost, \"https://time.geekbang.org/serv/v3/source_auth/video_play_auth\", params, heanders)\n\tif err != nil {\n\t\treturn nil, errors.WithStack(err)\n\t}\n\tdefer res.Body.Close() // nolint\n\n\tvar playAuth videoPlayAuth\n\tif err = json.NewDecoder(res.Body).Decode(&playAuth); err != nil {\n\t\treturn nil, errors.WithStack(err)\n\t}","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/iawia002/lux/blob/dd00f6d258d80b6684a0b9402d7124e5c18ef42f/extractors/geekbang/geekbang.go#L91-L127","documentation":"The geekbang extractor POSTs to time.geekbang.org/serv/v1/article; when the API answers code < 0 it re-throws the server's own error field, a json.RawMessage converted with string(). The message you see is whatever GeekBang returned — almost always an authentication or permission problem, not a parser failure.","triggerScenarios":"Missing, expired or logged-out Cookie header on the article request; malformed article id from the URL; an account that cannot access the article.","commonSituations":"Forgetting -c; partially pasted cookies; long-running batches where the session expires mid-run.","solutions":["Log in at time.geekbang.org, export the cookie, and run lux -c cookie.txt <article-url> (the -c value may be a file path or the raw string).","Confirm the same article opens in a browser using that session.","If the server message is empty, dump the raw response body to read the code/error fields directly."],"exampleFix":"// before\n$ lux \"https://time.geekbang.org/column/article/123456\"\n// after\n$ lux -c cookie.txt \"https://time.geekbang.org/column/article/123456\"","handlingStrategy":"try-catch","validationCode":"if strings.TrimSpace(cookie) == \"\" {\n\treturn errors.New(\"geekbang requires a logged-in cookie: pass -c <cookie-or-file>\")\n}","typeGuard":null,"tryCatchPattern":"Catch and surface the server-provided message verbatim — it already states the real reason (login, permission, bad id). Map it to a re-auth workflow: re-export the cookie and retry the single URL.","preventionTips":["Always pass a logged-in cookie for geekbang URLs","Export cookies fresh per session; they expire","Verify article access in the browser with the same account before batching"],"tags":["geekbang","auth","api","paid-content"],"backgroundTag":null,"analyzedSha":"dd00f6d258d80b6684a0b9402d7124e5c18ef42f","analyzedAt":"2026-08-15T16:57:31.080Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}