Starting a render from a callback gives error “Missing 'window' in context”?
Create an override dictionary.


Pass the context dictionary 

bpy.ops.render.render(od, "INVOKE_DEFAULT")
Made a complete copy of context.  This is somewhat dangerous since an object reference to a removed object may be accessed which will core dump blender.  I have a feeling the context members required to override hinges on the render display mode selected. with new window scene.render.display_mode = 'WINDOW' mode, it appears only the context.window is needed.


Have put in a count to stop after 5 renders to test.


Test run, code slightly altered (highlighted) to render frames 50, 40, 30, 20 and 10. In image editor display mode, renders to the image editor (if no open images) or opens one in the largest area

import time, bpy, functools

count = 5
def render(od):
    global count
    count -= 1
    timestr = time.strftime("%Y%m%d-%H%M%S")
    print(timestr)
    # I get no error in the line below
    bpy.ops.render.render(od, "INVOKE_DEFAULT")

    return 2 if count else None

def loop(c):
    print("LOOP", count)

    # override
    c["scene"].frame_set(10 * count)
    return render(c)


if __name__ == '__main__':
    f = functools.partial(loop, bpy.context.copy())

    bpy.app.timers.register(f, first_interval=5.0)