Peter's quite right about the problem, of course. However, this entire function is unnecessarily slow and complex - that repeated string concatenation will be horrible for performance, and PL/PgSQL loops are best avoided when you can anyway.
You can do the same job with an ordinary SQL function using generate_subscripts
:
CREATE OR REPLACE FUNCTION intarr_to_hex_string(integer[]) RETURNS text AS $$
SELECT
string_agg(
lpad(to_hex($1[x]),2,'0'),
''
order by x
)
FROM generate_subscripts($1,1) x;
$$ LANGUAGE sql;
The above version expects an integer array, but you can accept text arrays with an overload:
CREATE OR REPLACE FUNCTION intarr_to_hex_string(text[]) RETURNS text AS $$
SELECT intarr_to_hex_string($1::integer[])
$$ LANGUAGE sql;
Note that no sanity check is done to make sure the hex string is two digits or less. You should really add a check where you use a CASE statement to execute a PL/PgSQL function that raises an error if there's bad input. Here's a complete example:
CREATE OR REPLACE FUNCTION raise_exception(text)
RETURNS void LANGUAGE plpgsql AS
$BODY$
BEGIN
RAISE EXCEPTION '%', $1;
END;
$BODY$;
CREATE OR REPLACE FUNCTION intarr_to_hex_string(integer[]) RETURNS text AS $$
SELECT
string_agg(lpad(
CASE WHEN $1[x] < 256 THEN
to_hex($1[x])
ELSE
raise_exception('Argument to intarr_to_hex_string contained value '||coalesce($1[x]::text,'NULL')||', expected all values in i[] to be 0 <= i < 256. Full argument was '||quote_literal($1)||'.')::text
END,
2, '0'),
''
order by x)
FROM generate_subscripts($1,1) x;
$$ LANGUAGE sql;