You need to disambiguate the column names from the parameter and variable names.
For example, in this line you use the same name "pid" to reference a variable and a table column, and MySQL is not behaving the way you want it to:
SELECT Name, PID into str, pid FROM PathNames WHERE NID=id LIMIT 1;
I like to use the prefix p_
for parameter names and v_
for variable names in order to guarantee that the variable names and parameter names will not conflict with column names.
Here's your function rewritten with that convention. It should work for you:
DROP FUNCTION IF EXISTS NID2PathName;
DELIMITER //
CREATE FUNCTION NID2PathName(p_nid INT UNSIGNED)
RETURNS TEXT DETERMINISTIC
BEGIN
DECLARE v_rtn TEXT;
DECLARE v_str TEXT;
DECLARE v_tmp TEXT;
DECLARE v_id INT UNSIGNED;
DECLARE v_pid INT UNSIGNED;
SET v_id := p_nid;
SET v_rtn := "";
SET v_str := "";
SET v_tmp := "";
WHILE v_id > 1 DO
SELECT Name, PID into v_str, v_pid FROM PathNames WHERE NID=v_id LIMIT 1;
SET v_rtn := CONCAT('/', v_str, v_rtn);
set v_id := v_pid;
END WHILE;
RETURN v_rtn;
END//
DELIMITER ;