Asset Filename Query using Product SKU
I'm basing this response on the incomplete statement {% set image = craft.assets.filename('').one() %}.


To get an asset named the same as the SKU of a Product's default Variant, try this:

{% set exampleImage = craft.assets({
    filename: "#{myProduct.defaultVariant.sku | lower}.*"
}).one() %}


This does a couple things:


Collapses the transformation of a product into a search string using Twig's string interpolation, and the filter you'd applied;
Appends .* to match all extensions (optional, but recommended, in the event you have some PNG, JPG, and JPEG images in your library);
Executes the query and returns a single Asset Element or null.


Always check you have results before attempting to access properties of your image:

{% if exampleImage %}
    &lt;img src="{{ exampleImage.url }}"&gt;
{% endif %}


I think the original problem you were encountering was that (by default) the filename query parameter matches strictly, meaning that your SKU would need to be the complete filename in order to be returned. You can view the fuzzy-matching syntax/options in the Asset Query documentation.



With respect to the overall structure of the code, I'd recommend an approach like this:

{# First, look for an attached image: #}

{% set image = myProduct.productImage.one() %}

{# If there wasn't one, try looking in the Asset library: #}

{% if not image %}
    {% set image = craft.assets({
        filename: "#{myProduct.defaultVariant.sku | lower}.*"
    }).one() %}
{% endif %}

{# We might still be missing an image. If so, fall back to fetching a specific one: #}

{% if not image %}
    {% set image = craft.assets({
        id: 9225
    }).one() %}
{% endif %}

{# Ok, now we're guaranteed to have one of the above images—we can safely use `image` the same, regardless of where it came from: #}

&lt;img src="{{ image.url }}"&gt;