I've actually had this problem, and sometimes still have this problem on my current team with people I've been working with for over a year.
Personally, I am a big fan of accountability, and that's why I struggle with the say nothing approach. Before I go on, keep in mind that accountability doesn't always mean telling someone their work is useless or that they haven't done anything meaningful for the team. It doesn't have to be degrading or a personal attack (Something I had to learn over time). Sometimes it could be a simple misunderstanding of priorities, unclear expectations of what to work on, weakness in areas where the work truly was, or maybe Joe has personal things going on in his life.
So how does accountability come into play? At the end of the day, we are all working on something to reach a goal. In software, it's typically to solve bugs, built out functionality in a system, or harden an existing product. These are basically the job requirements at a very low level for a programmer working on a code base at a company. In my opinion, if someone isn't doing their tasks, not only is it a liability for you and the team, it's a waste of the company's resources (time + money).
Something that will affect the scope of what makes sense for you based on your question involved: Who, in the Team Lead's absence (or otherwise), delegates and prioritizes work? This is the person who should be held accountable in the same light as Joe.
...did nothing useful and actually slowed us down.
This is a very big statement and will most likely be perceived as a personal attack. What will help is re-constructing your criticism to be more geared towards
- Understanding how Joe started working on the Tasks that he deemed important
- What Tasks The Team feels were more important and valuable that he should have been working on
- You are concerned that the work he was doing wasn't contributing towards the goal of the Sprint
You need to show that your concerns are valid and that they are about the work [not] getting done and they are not actually with the individual. (If you truly do not like Joe, find another team, or ultimately another job. It's not worth the negativity it brings to be around someone you dislike)
He would make tasks out of thin air that weren't requirements (unknown
to us at the time), ask us for help after he spent way too long on
them and then eventually just not complete it.
This feels like "bad house-keeping" since there was work going on that wasn't being tracked, no one was asking why this work was being done, and it seems like people were focused on other things and lost sight of, again, the goal of the sprint. When Joe asked for help - that gave you a very small window of opportunity to dig a little deeper and determine why he was working on these tasks and what they had to do with your plate of work. In the Sprint, the team should usually have a good idea of what's left to do and the higher priority items on the backlog (that I'm assuming everyone has visibility into). Work in progress that does not get completed is not always a bad thing, depending on the work. For example, if Joe was researching a new technology that would help speed up database connections, for example, then I would say that's potentially valuable, although the priority of other work could come first. Open communication resolves issues like this.
Ultimately, a Team Lead has much more on their plate (usually) than the developers that work under them. The Team Lead will not go through all code reviews and check-ins. I believe this is the case because there is mutual understanding and respect that your peers will do their work as prescribed and if any issues arise (we couldn't do X because of a dependency on Y), they will be brought to light during a meeting. It doesn't do a Team Lead any good to micro-manage 2-weeks worth of work by reviewing every check-in. That's where you need to focus your energy if you're going to speak up about this, and refrain yourself from personally attacking Joe - it will do more harm than good.
Again, the things to focus on here are: Making sure your Team Lead knows that this is a genuine concern of yours and you aren't simply complaining. What should everyone be working on? Who delegates that work when the Team Lead is MIA? Have open communication about the work being done and how it contributes to the goal of the Sprint / Team / Product. If you don't feel like something being worked on is valuable because there are higher priority items - there's nothing wrong with that, but you have to build your case on facts.