glanceapp/glance · error · errNoContent

%w: could not fetch list of post IDs

Error message

%w: could not fetch list of post IDs

What it means

The request to the Hacker News Firebase API (https://hacker-news.firebaseio.com/v0/<sort>stories.json) failed during request execution or JSON decode, and is wrapped with errNoContent so the widget renders an empty list. The underlying decodeJsonFromRequest error (network, non-200, or bad JSON) is discarded from the message.

Source

Thrown at internal/glance/widget-hacker-news.go:82

func (widget *hackerNewsWidget) Render() template.HTML {
	return widget.renderTemplate(widget, forumPostsTemplate)
}

type hackerNewsPostResponseJson struct {
	Id           int    `json:"id"`
	Score        int    `json:"score"`
	Title        string `json:"title"`
	TargetUrl    string `json:"url,omitempty"`
	CommentCount int    `json:"descendants"`
	TimePosted   int64  `json:"time"`
}

func fetchHackerNewsPostIds(sort string) ([]int, error) {
	request, _ := http.NewRequest("GET", fmt.Sprintf("https://hacker-news.firebaseio.com/v0/%sstories.json", sort), nil)
	response, err := decodeJsonFromRequest[[]int](defaultHTTPClient, request)
	if err != nil {
		return nil, fmt.Errorf("%w: could not fetch list of post IDs", errNoContent)
	}

	return response, nil
}

func fetchHackerNewsPostsFromIds(postIds []int, commentsUrlTemplate string) (forumPostList, error) {
	requests := make([]*http.Request, len(postIds))

	for i, id := range postIds {
		request, _ := http.NewRequest("GET", fmt.Sprintf("https://hacker-news.firebaseio.com/v0/item/%d.json", id), nil)
		requests[i] = request
	}

	task := decodeJsonFromRequestTask[hackerNewsPostResponseJson](defaultHTTPClient)
	job := newJob(task, requests).withWorkers(30)
	results, errs, err := workerPoolDo(job)
	if err != nil {
		return nil, err

View on GitHub (pinned to 91324e8de7)

Solutions

  1. Verify connectivity: curl https://hacker-news.firebaseio.com/v0/topstories.json
  2. Fix container DNS/egress (network policy, proxy env vars)
  3. If Firebase is temporarily down, wait and let the widget's next update cycle retry
Defensive patterns

Strategy: retry

Try / catch

ids, err := fetchHackerNewsPostIds(sort)
if err != nil {
    if errors.Is(err, errNoContent) {
        // transient third-party failure: keep previous cycle's posts
        return widget.lastGoodPosts, nil
    }
    return nil, err
}

Prevention

When it happens

Trigger: Firebase API unreachable, rate-limiting, returning non-200, or network egress blocked from the glance host.

Common situations: Self-hosted glance in a container without internet egress; DNS failure for firebaseio.com; transient Firebase API outage; corporate proxy blocking the request.

Related errors


AI-assisted analysis of glanceapp/glance@91324e8de7 (2026-08-15). Data as JSON: /api/errors/80fcdaf9731929e1. Report an issue: GitHub.