\temp with many LaTeX-packages is a scratch-macro. So code not stemming from you might override (re)definitions of \temp stemming from code written by you.
In order to prevent such clashes in the following \Mytemp is used instead of \temp.
Donald E. Knuth in his TeXbook describes TeX analogously to a beast which has eyes, mouth and digestive tract.
I tried to outline the different stages of the processing of a .tex-file, using that analogy, in my answers to
With \def/\gdef expansion is suppressed while tokens forming the definition text go down TeX's gullet. Thus with \def/\gdef the tokens forming the definition text are not expanded when reaching the stomach where performing the assignment takes place.
With \edef/\xdef expansion is not suppressed while tokens forming the definition text go down TeX's gullet. Thus with \edef/\xdef the tokens forming the definition text in a "process of regurgitation" are "fully" expanded when reaching the stomach where performing the assignment takes place.
The crucial point is: \underbrace itself is a macro which at some stage of expansion yields some #. At the time when expansion is done and in TeX's stomach the attempt of performing the assignment underlying \xdef takes place, these # erroneously are taken for reference to some parameter of the macro that is to be defined/redefined.
Besides this you might like to cope with the fact that definitions can be nested inside definitions whereby which each "nesting-level" another level of doubling hashes for denoting parameters of the definition in that definition-level is needed and with the fact that expanding a macro reduces two consecutive hashes occurring in that macro's definition text the a single hash.
E.g., if you do
\long\def\hashcarrier{################A}
\long\xdef\hashcarrier{\hashcarrier B}
\show\hashcarrier
\long\xdef\hashcarrier{\hashcarrier C}
\show\hashcarrier
\long\xdef\hashcarrier{\hashcarrier D}
\show\hashcarrier
%% If you activate the following lines you get error-message about
%% illegal parameter number in definition of \hashcarrier because
%% things were reduced to single hashes that are taken for reference
%% to parameters of the current definition-level while the parameter-text
%% of the current definition-level doesn't denote any parameter at all
%% and parameters must be numbered consecutively from 1 to 9 instead of
%% a thing like A:
%\long\xdef\hashcarrier{\hashcarrier E}
%\show\hashcarrier
\csname bye\endcsname
\stop
you get the following output on terminal / in .log-file
> \hashcarrier=\long macro:
->########AB.
l.3 \show\hashcarrier
?
> \hashcarrier=\long macro:
->####ABC.
l.5 \show\hashcarrier
?
> \hashcarrier=\long macro:
->##ABCD.
l.7 \show\hashcarrier
?
(\long means that in case the macro in question processes arguments each of these arguments may contain the control-word-token \par.)
You can prevent both unwanted expansion and reducing amount of hashes via \xdef and \unexpanded:
\documentclass{article}
\newcommand\Mytemp{}%
\long\def\updateMytemp#1_#2{%
\long\xdef\Mytemp{\unexpanded\expandafter{\Mytemp\underbrace{#1}_{#2}}}%
}%
\begin{document}
\updateMytemp{a}_{b}
\show\Mytemp
[\Mytemp]
\updateMytemp{c}_{d}
\show\Mytemp
[\Mytemp]
\end{document}
Or --legacy style-- via \xdef and \the-expansion of a token-register:
\documentclass{article}
\newtoks\MyScratchtoks
\newcommand\Mytemp{}%
\long\def\updateMytemp#1_#2{%
\MyScratchtoks\expandafter{\Mytemp\underbrace{#1}_{#2}}%
\long\xdef\Mytemp{\the\MyScratchtoks}%
}%
\begin{document}
\updateMytemp{a}_{b}
\show\Mytemp
[\Mytemp]
\updateMytemp{c}_{d}
\show\Mytemp
[\Mytemp]
\end{document}
I suggest doing something more generic using LaTeX's \g@addto@macro:
\documentclass{article}
\newcommand\Mytemp{}%
\makeatletter\newcommand\updateMytemp[1]{\g@addto@macro{\Mytemp}{#1}}\makeatother
\begin{document}
\updateMytemp{\underbrace{a}_{b}}
\show\Mytemp
[\Mytemp]
\updateMytemp{\underbrace{c}_{d}}
\show\Mytemp
[\Mytemp]
\end{document}
With all three examples you get something like the following messages on console and in the .log-file:
> \Mytemp=macro:
->\underbrace {a}_{b}.
l.9 \show\Mytemp
?
> \Mytemp=macro:
->\underbrace {a}{b}\underbrace {c}{d}.
l.13 \show\Mytemp
With all three examples you get the following pdf-output:

Another hint:
LaTeX's \newcommand, \NewDocumentCommand etc trigger error-messages in case the command to be defined is already defined or cannot be defined due to containing the leading phrase "end" in its name. You can achieve the same behavior with assignments performed via \def/\gdef/\edef/\xdef by wrapping them into LaTeX's \@ifdefinable-test.
E.g., instead of just
\long\def\updateMytemp#1_#2{%
\long\xdef\Mytemp{\unexpanded\expandafter{\Mytemp\underbrace{#1}_{#2}}}%
}%
you would do
\makeatletter
\@ifdefinable{\updateMytemp}{%
\long\def\updateMytemp#1_#2{%
\long\xdef\Mytemp{\unexpanded\expandafter{\Mytemp\underbrace{#1}_{#2}}}%
}%
}%
\makeatother
If you wonder what \makeatletter/\makeatother is about:
Simplified speaking TeX/LaTeX usually allow only ordinary alphabetic letters a..z/A..Z as components of names of control-word-tokens.
\makeatletter is a directive for telling LaTeX that henceforth @ shall be allowed as component of names of control-word-tokens, too.
\makeatother is a directive for telling LaTeX that henceforth @ shall a be thing which is not allowed as component of names of control-word-tokens.
Without \makeatletter/\makeatother you could use \csname..\endcsname for gathering the name of the control sequence token from what is between \csname..\endcsname and delivering that control sequence token:
\csname @ifdefinable\endcsname{\updateMytemp}{%
\long\def\updateMytemp#1_#2{%
\long\xdef\Mytemp{\unexpanded\expandafter{\Mytemp\underbrace{#1}_{#2}}}%
}%
}%
\tempto store content that should stay. That is a name other commands can easily internally use for "temporary" content too. – Ulrike Fischer Jun 27 '22 at 07:13