My first guess would be that the user executing the job is not the same user that you use when testing the code. Thus the job executing user does not in fact have the correct privileges. Run a test job that does nothing but raise_application_error(-20999,’user-‘||user); and find out who he thinks he is when he runs your job.
My second guess is that there is once again a privilege constraint that oracle has implemented regarding jobs run via the job queue. As you recall, privileges behave differently under PLSQL than straight from SQLPLUS. If you are doing some kind of dynamic sql, you may need direct grants to the rlated objects rather than grants received via a role. If so, this should be documented in the relevant manual.
My third guess is that it is related to your use of synonyms from a different schema. I wager you suspect this as well or you would not have included this information. If this is so, then create your grants using the WITH GRANT OPTION (or whatever the current equivelant is these days).
My fourth guess is a wild one. I have not clue if this is true or not, but maybe the job queue executes its wrapper as a dynamic sql call. I never really paid much attention to it. If so then what I said for guess#2 above about direct grants would come into play.
Good luck, Kevin