Please fix: Unknown or expired link.
I'm pretty sure that the HN community likes to read thoughtful, thoroughly researched comments that are somewhat longer than one-liners. But whenever I take more than a few minutes to write a comment, I am greeted with the following error message as soon as I hit "Submit":
Unknown or expired link.
Fortunately, I can usually hit the Back button, refresh the page, and resubmit my comment without losing the contents of the textarea. Anyway, I try to be extra careful and copy the comment to the clipboard before I hit "Submit" if I feel like it's been more than a few minutes since I started writing.But this should not be necessary in the first place.
Please increase the timeout on your CSRF tokens (or whatever it is that triggers the error message above) to something more user-friendly. I would suggest a sensible default of 86400 seconds.
Thanks.
76 comments
[ 5.5 ms ] story [ 182 ms ] thread* Although HTTP connections are normally stateless, HN has a login system for account holders, which means there's a state, a connection, associated with each logged-in user.
* Because of the state information associated with logins, A Web server has a limited number of login connections it can handle.
* To serve the maximum number of visitors, a server needs to recycle connections that are no longer in use.
* There's no reliable heartbeat method between browser and server that a server can use to determine whether a given connection is still in use. Also, heartbeats would represent an extra traffic load on the server. And now that tabs have become popular, there's no way to be sure that a heartbeat response isn't from an unused, forgotten tab among dozens.
* Therefore, after a connection has not seen packet requests for a set time interval, the server expires the connection to make it available to other visitors.
* The shorter the timeout, the more connections the server can handle.
> I would suggest a sensible default of 86400 seconds.
Let's say the server can handle 2048 simultaneous login sessions (I don't know the actual number). According to your suggestion, after the first 2048 visitors log in, the server would refuse to accept any new logins for 24 hours. This isn't realistic.
Here's how I handle the problem -- if I decide a reply is going to take more than a few seconds, I transfer my reply to a text editor and let the connection expire. When my long-winded reply is ready, I refresh the original page, paste my reply in, and click "Add Comment".
I hope this helps.
Even assuming it's all but impossible to fix given the implementation in Arc, surely it would be possible to automatically reassociate the post with whatever the current function id is? It seems to be as much a user experience problem as anything.
IMO the reasons presented for this "Feature" should be changed to "lazy programming". cause that's all it is.
The reason for 'Unknown or Expired Link' is that HN runs on a webserver that uses continuations to maintain state. The continuations are stored in a table and based on load individual table entries get flushed to make room for new entries as needed. The message is actually always the result of an unknown link because the hash is no longer in the table.
Your experiment worked because the relevant continuation [state reference] was available after disconnect e.g. the 'route' so to speak was still valid.
Now obviously one might wonder why HN works this way. The reason is that the HN codebase came about as a way of field testing Arc [Graham's 100 year language]. Until rather recently, HN ran on a single server. It still uses relatively few lines of code.
This is really the key point: continuations are the wrong way to write this kind of application. It's significantly more work and there's no benefit from doing so but it allowed someone to test a pet idea and, having done so, fixing it would mean admitting that doing something because it's cool isn't good engineering.
https://news.ycombinator.com/item?id=7651525
The application and implementation decisions are YC's. The essay explains their rationales.
There is no need to keep an HTTP connection open in order for the server to log people in or recognize when a valid token has been submitted with a form.
You're making excuses for a particular setup - this is not something which holds true of all web servers. It's quite possible to store the state necessary to allow 10000 simultaneous logins if you use cookies and a db to store your state, rather than relying on in-memory state and fragile continuation links like this (created a few minutes ago):
https://news.ycombinator.com/x?fnid=l5qgIWgvnRbHE7owLEaPMw
or tying replies to stored state on the server which expires within minutes. Many large scale sites manage it, I suppose because they don't store data like this in memory or urls. I'm not sure about this idea of storing state in urls, it often backfires, and urls should identify resources and actions, not store state.
There is no good reason the server cannot receive a POST request from an authenticated user against a node id, and perform the requested action (post my reply please), no matter how many intervening logins/actions it has handled.
Looking at the form in question (reply forms) reveals why it does break:
The server stores a continuation in the comment reply form, which (like the more link above) expires very quickly. The reason it expires is presumably because the server keeps a list of these fnids in memory, and as you say the list is finite, but it doesn't have to do that. There are other ways to create a CSRF (if that's what they use this for) which won't expire so quickly, and this problem is not one which many sites experience.It is annoying just how quickly reply links, more links etc expire on this site, and if the site used a different method to sign reply forms or construct other links they could get rid of this issue. Keeping data in memory like this will become more and more of a problem as the site scales - eventually things would break in seconds with enough load - that's clearly not acceptable.
Most often, the server just needs to set a flag associating an auth token with a given user (for whom it has a persistent representation, e.g. in a database.) Lookups against this token => user hash/map/table should be very cheap, especially if it's kept in memory. Further, even for tens of thousands of concurrent users, that's not a lot of memory overhead (1KB/authed user would be a generous upper bound, and that would still only be 10MB of RAM per 10k concurrent users.) Could be that HN is running on a 1990s-era desktop with 256MB of memory in someone's office and that this is an actual resource constraint issue--but my hunch is that this problem lies on the software side, not the hardware/resource side.
Yes, obviously it would be great if X were increased. But doing so would require an increase in server resources or a significant change in the way HN's backend works; neither of these options is free. That is the reason why things are this way.
This is an old debate. See, for example: https://github.com/HackerNews/HN/issues/11
The solution should be pretty straightforward:
They already check authentication on these actions anyway as you'll see if you try upvote links from another user without login, all that would be required would be to use CSRF instead of these closures to handle posts like this - the closures are not a workable solution on a large site, and I'd contend are dangerous on a small site - they throw away a lot of the advantages of HTTP for no appreciable gains.Things like the more link are particularly pointless, they could just use something like:
This would change over time like the existing home page, but there's no reason for a simple GET request like this to expire.I don't know much about the internals of Arc, but maybe it would be possible to serialise the continuation data, combine it with a reasonable expiry time, apply some form of authenticated encryption to this, and supply that as the fnid? And reverse the process - with appropriate integrity checks - when the fnid is submitted. Then you have your state distributed at the client-side instead of all being kept on the server, so it can scale more effectively.
EDIT: Nevermind, just realised that this very suggestion is addressed here, and it's more difficult than I anticipated https://github.com/HackerNews/HN/issues/11#issuecomment-3215...
I don't think they should try to serialise fnids, but just get rid of them completely. What state is required for a posted reply other than the three things outlined above + CSRF protection?
I think the most common technique I've seen for generating CSRF token is to compute an HMAC of the immutable request parameters.
I'm guessing that's what HN already implements for voting, as the token is dependent on user id and the id of the thing being voted on, and kind of looks like an SHA-1 hash.
a) this is technically incorrect – you can trivially handle this using signed cookies to store the logged in user
b) even using traditional database or filesystem based approaches, those limits would be aggressive even if the site was hosted on an iPhone – you're talking tens of bytes per session.
> To serve the maximum number of visitors, a server needs to recycle connections that are no longer in use.
Also technically wrong: if you aren't doing anything, you aren't causing any load whatsoever on the server. This would be different for something like a chat site using WebSockets but for a vanilla app like HN this is not an issue.
Also, again, even if you were using a persistent connection the absolute technical limits are much, much higher than the traffic HN sees - hundreds of thousands of simultaneous users.
> There's no reliable heartbeat method between browser and server that a server can use to determine whether a given connection is still in use.
Again, technically wrong: plain HTTP sites don't maintain persistent connections but in the case of something like a WebSocket connection you'd simply use TCP keepalives, which are a mature standard feature and very low overhead.
You appear to have confused the concept of a session with something which is actually happening at the network level. Try reading something about the HTTP request cycle (e.g. http://www.slideshare.net/cczona/full-stack-full-circle-what...) for basic background and after that move on to some discussion about the work done to make servers which can handle many simultaneous connections - the C10K problem was the original work tuning operating systems to handle tens of thousands of simultaneous connections and was large a non-issue at the network / basic HTTP leel by the mid-2000s:
http://bulk.fefe.de/scalability/
By now a single server can be assumed to handle hundreds of thousands of simultaneous connections at the network level – assuming, of course, that you have capacity to actual do whatever work those connections are used for. Idle users typing text into a form wouldn't be a problem even if it did use a persistent connection.
[1]: http://motherfuckingwebsite.com/
http://paulgraham.com/hackernews.html
Section 2.2.1, Timing Adjustable (http://www.w3.org/TR/WCAG20/#time-limits-required-behaviors):
----
2.2.1 Timing Adjustable: For each time limit that is set by the content, at least one of the following is true: (Level A)
- Turn off: The user is allowed to turn off the time limit before encountering it; or
- Adjust: The user is allowed to adjust the time limit before encountering it over a wide range that is at least ten times the length of the default setting; or
- Extend: The user is warned before time expires and given at least 20 seconds to extend the time limit with a simple action (for example, "press the space bar"), and the user is allowed to extend the time limit at least ten times; or
- Real-time Exception: The time limit is a required part of a real-time event (for example, an auction), and no alternative to the time limit is possible; or
- Essential Exception: The time limit is essential and extending it would invalidate the activity; or
- 20 Hour Exception: The time limit is longer than 20 hours.
Note: This success criterion helps ensure that users can complete tasks without unexpected changes in content or context that are a result of a time limit. This success criterion should be considered in conjunction with Success Criterion 3.2.1, which puts limits on changes of content or context as a result of user action.
----
Yea, verily! HN isn’t even Level A (the most basic level that "everyone" should comply with) compliant. Through this, HN fails Accessibility 101. (Its text colour choices are also often dubious as far as contrast goes—that’s covered in WCAG 2.0 as well, of course.)
I simply don’t care about the technical reasons. The choice of coroutines to back all of these things has broken the basic accessibility of all the content.
Exactly. This is actually a good example of More is Less.
This same problem can happen in a PHP application, and it can be avoided in a Racket web framework application that uses continuations.
Please, for the love of everything that is good and pure and true, make the font larger!
Sincerely, Blind among blind
Edit: please don't suggest one of the other HN wrappers. I know they exist. I don't want to hand over my HN password to them. My HN identity is important to me, so unless I can run my own wrapper on my own servers I don't want it.
Edit edit: I believe if HN mods/operators announced a contest for best mobile design they'd get a ton of submissions. Sadly I am not a designer and could not participate, but I am sure the amount of submissions would be huge.
https://news.ycombinator.com/item?id=7606298
What about one of the many apps? Have you tried news:yc?
>Internally, the web server associates a token called the fnid with each instance of a link or form, and records the continuation function for each token. Periodically, old fnids are deleted.
[1]: http://arclanguage.github.io/ref/srv.html
Any idea where the fnids are stored and how they are garbage-collected? Could it be that they're just dumped into a memcached instance and older fnids get pushed out whenever the memory limit is reached?
If you're on Chrome use HackerNews Enhancement Suite.
https://chrome.google.com/webstore/detail/hacker-news-enhanc...
No more ass-ugly hackernews font choices and colors.
The only reason people come here is the content.
I consider this a good thing. It attracts the right kind of people.
I hope that you're not involved in product design. This thought process is not good for anyone.
I've maintained for years that the key to a high quality online forum is for it to be limited in some way. It can be limited by bugs. Limited by nobody advertising that it exists. Limited by having a very focused topic of discussion. I'm willing to believe that it can be limited by moderation, but I self-select out of those forums so don't know.
But without some sort of limiting you get what happened to Usenet, Slashdot, kuro5hin, the main page of Reddit, and so on. Which is that they became the place that everyone knew that they should go. And then the noise went up faster than the signal, resulting in a poor signal to noise ratio. And then the best people found new forums to go to, and slowly disappeared.
Of course if you make the limiting TOO effective, eventually nobody will be left. There is a balance to be had.
And this only applies to high quality content of the kind that I want to engage with. Which is admittedly not to everyone's taste. It is not a way to make something popular.
This has been a public service announcement.
https://github.com/HackerNews/HN/issues/11
so the more link on:
https://news.ycombinator.com/news
would point to:
https://news.ycombinator.com/news/2
and so on.... This would free up many fnids for use elsewhere, and also make the secondary list pages more easily cacheable and reduce load on the server.
The same could be done for other lists which currently use fnids without any appreciable change in the user experience or probably much change in the server code.
Is the internal activity causing this unpopular behavior supposed to do this, in the first place? If the site is indeed behaving exactly as its designers want it to, then that's a rather separate debate as opposed to simply ways and means.
I'm not saying I agree with the behavior; I'm just trying to see what should be debated to start with.
kogir and I talked recently about getting rid of "unknown or expired link". It's on our list. There are a lot of things on the list; we don't know yet when we'll get to it.
There's work ongoing to make HN more usable on mobile. This will likely roll out sooner than the above. We intend to roll it out incrementally, starting with the front page. We'll give people lots of notice so anyone running scrapers that are affected (like me!) will have time to change.
The look and feel of HN is unlikely to change much. We can argue about that one till the cows come home. I'm tempted to—my opinions are as strong as many of yours—but that doesn't seem like the best idea right now.
Feature requests should go to https://news.ycombinator.com/item?id=363. Software bugs should go to https://github.com/HackerNews/HN/issues. That would have been the appropriate destination for the OP, and indeed this issue has been posted about there.
Threads like the current one get lots of upvotes and comments, but they've never been on topic for HN. I'm going to bury this one now.
It would be on topic to discuss the implementation of any other site.
I can understand why it's annoying for the staff to have to encounter these threads so often - it's annoying for users to keep running into dead links. But I don't think it's entirely true that this topic has no value to the community at large. Having opinions and discussing things is kind of what forums are supposed to be about.
Though I would disagree with the premise that meta-discussion, necessarily, is a bad thing. At the very least given the nature of the site and its userbase, it's going to be inevitable.
[^1]: http://www.nicemice.net/par/
[^2]: http://jblevins.org/projects/markdown-mode/
[^3]: I just wish markdown-mode would renumber the footnotes if I go back and insert a new footnote. As it is I have to pipe the output through pandoc