Pseudo-record errors have been a fairly common problem, the problem is convincing Postgres it has a working rowset. There are times it might be easier to work with an intermediary recordtype that looks like a pseudo-record but serves as a fully materialized recordset, and without creating & casting to a formal "type" [record type].
/*
-- This wont work, causes pseudo-type record error
*/
CREATE TEMP TABLE tmpErrPseudoSave AS
SELECT ROW( col2, col1 ) AS anonrow FROM tmpOrigDat ;
As of PostgreSql Ver. 13 there is a decent work-around. This is accomplished by encapsulating the returning set as a inner-query CTE, that the outer query can see & use it as a fully materialized state.
It's even possible to cast the rowtype to a new, compatible type, on-the-fly:
Such column aliasing could be table-driven from a data dictionary, using an anonymous DO LOOP to build matching column aliases, in their correct matching ordinal positions.
PRIOR TO PostgreSql 13, saving the intermediary pseudo-typed row-type isn't possible, you'll have to cast to a pre-defined row-type (stored either as a formal Postgres type, table, or temp table).
FULL demo at dbfiddle.uk