In the good old days of regular OpenGL, it was fairly easy to determine if a texture upload was successful - after calling glTexImage2D you could use glGetTexLevelParameteriv with GL_TEXTURE_WIDTH and GL_TEXTURE_HEIGHT as parameters. GLES, however, doesn't seem to allow this, and as far as I can tell has no mechanism to determine whether a texture has actually been successfully provided to the card (for example, glGetError is only set for things that will not succeed, as opposed to things that did not succeed).
The application I'm working on is always straddling the barrier between having enough VRAM available and not (and there's often a lot of dynamically-allocated FBOs and the like flying around, complicating matters further), and if an important texture upload fails I need to know if I need to purge an unimportant texture and retry.
I fear that this is not possible at the moment. The entire OpenGL state that contained texture size is now removed (according to GLES 2.0.25 specs). As you correctly stated, there is no error generated on texture upload going wrong (that is sadly by design). Proxy textures were removed, and it was reported by people that they were often not supported/broken on PC-class GPUs. So what now?
You could try and read the texture contents back via framebuffer object (maybe not the whole texture, but only corner points / every 32nd pixel / ...). It would not be very fast, but it should work. Maybe you could also use framebuffer completeness test with the texture attached (but that seems to be only limited to image internal format, which may or may not be set in case the texture upload fails because of low memory - you would have to test that).
You can (in theory) determine the amount of available memory by creating a renderbuffer object, the spec states that glRenderbufferStorage() will fail with GL_OUT_OF_MEMORY, so that should be quite reliable.
It would be pretty easy to test for free space before allocating the texture, then deleting the renderbuffer (if successful) and then allocating the texture itself. Keep in mind that with mipmaps the texture would take a little more than 1.33x storage for base level.
Even better would be to determine available memory at application startup (maybe after compiling the shaders and allocating other objects where it is not easy to estimate memory footprint) and to keep track of object allocations to see how much memory is left. It seems complicated, but if the OpenGL objects are wrapped in classes, it should be pretty easy.