A real number is said to be computable if a finite, terminating algorithm can compute it to arbitrary precision. Since algorithms are countable (for example, one may list all possible c programs in lexicographical order), so are computable numbers.
Then, one may build the list of all computable numbers, in the order they appear in the list of all algorithms. One may now extract a new number from this list, much like in Cantor's diagonal argument, by having it's $n$th digit to be different from the $n$th digit of the $n$th computable number (e.g., $x\mapsto (x+1)\;mod\;10$). This number will not be computable as it is different from every number in the list. Yet, it looks like we have an algorithm to find it.
What seems to be the trick here, is that no algorithm for building the list of computable numbers exists, as it should have to decide whether a given algorithm does not halt in order to skip it. To avoid a contraddiction, the halting problem must be undecidable.
Can this paradox be turned into an actual formal proof, or some fine details of formal logic get in the way, making the argument flawed?
It is correct that you can effectively list all "algorithms" (or better, all partial computable functions $\mathbb{N}\to\mathbb{N}$), but this does not imply that you can list all the computable (real) numbers. For the sake of this argument (and to ignore problems like multiple representations of reals and such), let us forget about numbers and let's talk about infinite strings of natural numbers. Your argument is essentially showing that you cannot computably list all the computable infinite strings, or, if prefer, you cannot computably list all and only the total computable functions $\mathbb{N}\to\mathbb{N}$.
As mentioned in the comments, the problem is that you can't (computably) tell if a machine is never going to halt or if it is just needs more time. Imagine for example that your $n$-th program does not seem to converge on the $n$-th digit. Your algorithm for computing the diagonal string should, in finite time, commit to choosing the $n$-th digit for the diagonal string. After that stage, the $n$-th algorithm can choose to produce exactly the digit that your algorithm picked.
To make it even more precise, let $(\varphi_e)_{e\in\mathbb{N}}$ be a computable list of all partial computable functions. Let $f:\subset \mathbb{N}\to\mathbb{N}$ be the partial computable function defined as $f(e):=\varphi_e(e)+1$. Clearly $f$ is partial (e.g. take $e$ be the index of the algorithm that never converges on any input). If there were a computable enumeration $(\varphi_{e_i})_{i\in\mathbb{N}}$ of all total computable functions (i.e. if the map $g(i):=e_i$ were computable), then $f$ restricted to $\{e_i : i\in\mathbb{N}\}$ would be total. In particular, $f\circ g$ would be a total computable function not listed in $(\varphi_{e_i})_{i\in\mathbb{N}}$.
Observe that knowing whether a program halts on a given input is not enough to tell whether a function is total or not (i.e. if it halts on every input). However, you argument can certainly be adapted to show that the halting problem is not computable: if it were computable you could effectively find an enumeration $(\psi_j)_{j\in\mathbb{N}}$ of all problems that halt on their index. It would be enough to start from $(\varphi_e)_{e\in\mathbb{N}}$ and then, for each $e$, check whether $\varphi_e(e)$ halts. Then modify the definition of $f$ saying that $f(e):=0$ if $\varphi_e(e)$ does not halt. Such $f$ would be total and computable, hence it would halt on its index, but is not enumerated in $(\psi_j)_{j\in\mathbb{N}}$, contradiction.