Undefined offset: 3 in custom function

You assumed get_field would always return images, but what if there are no images to return?

   $images = get_field('fl_gallery');
   $image  = $images[$no];

The code never checks $images to see if it’s empty, or an error value.

On top of that, what if it returned images, but it returned 3 images, and $no is 4? You can’t access something that doesn’t exist without warnings, you have to check first. This is why you’re getting PHP warnings.

For example:

if ( empty( $images ) ) {
    // no images!
}

if ( empty( $images[$no] ) ) {
    // that image doesn't exist
}

However, you’re using get_field which is an ACF API, not a WordPress API. You will need to consult the ACF documentation on what that function does when it encounters problems, and how to handle the error. It may not return an array at all but final HTML.

You’ll also want to add more validation. For example [photo_shortcode no=9000] or [photo_shortcodo no="-1"] or [photo_shortcode no="0.5"] are all numeric and would generate those PHP warnings

Sidenote: extract reduces security, makes code unreadable by machines and tools, and can overwrite variables unexpectedly enabling security holes and bugs. Never use it.