Repository: PrefectHQ/prefect

Issue:
Result location not getting formatted
## Description
<!-- A clear description of the bug -->
Placeholder values in Result `location` are not filled in, Result is not found and the flow fails. Although the previous task saved the results in the correct location.

```
5 November 2020,03:16:33 	prefect.LocalResult	DEBUG	Starting to upload result to test_flow/05-11_14-16-28/A-6007ec12-1de1-42c0-a9db-7cc500e017e7.prefect_result...
5 November 2020,03:16:33 	prefect.LocalResult	DEBUG	Finished uploading result to /home/user/some_path/results/test_flow/05-11_14-16-28/A-6007ec12-1de1-42c0-a9db-7cc500e017e7.prefect_result...
...
5 November 2020,03:16:33 	prefect.CloudTaskRunner	INFO	Task 'C': Starting task run...
5 November 2020,03:16:33 	prefect.LocalResult	DEBUG	Starting to read result from {flow_name}/{scheduled_start_time:%d-%m_%H-%M-%S}/{task_full_name}-{task_run_id}.prefect_result...
```

I believe this is caused by a state dependency between tasks `A -> C`, because when I remove that edge, the flow runs as expected. 
![image](https://user-images.githubusercontent.com/42157644/98255796-18f54680-1f7e-11eb-8c3e-c941bb46b2ec.png)



## Expected Behavior
<!-- What did you expect to happen instead? -->
I would expect the task C to pick up the results from the correct location and the flow to be successful.



## Reproduction
<!-- A minimal example that exhibits the behavior. -->
```python
import os
from typing import List

import prefect
from prefect import Flow, task
from prefect.engine.results import LocalResult


@task(name="A")
def task_a() -> List[int]:
    return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


@task(name="B")
def task_b(foo: List) -> None:
    prefect.context.logger.info(f"Task B {foo}")


@task(name="C")
def task_c(foo: List[int]) -> None:
    prefect.context.logger.info(f"Task C {foo}")


result_directory = os.path.abspath(
    os.path.join(os.path.dirname(__file__), "..", "results")
)

result = LocalResult(
    dir=result_directory,
    location="{flow_name}/"
    "{scheduled_start_time:%d-%m_%H-%M-%S}/"
    "{task_full_name}-{task_run_id}.prefect_result",
)

with Flow(name="test_flow", result=result) as flow:
    a = task_a()
    b = task_b(a)
    c = task_c(a)

    # Commenting out this line removes the state dependency and the flow works
    # just fine
    flow.set_dependencies(task=c, upstream_tasks=[b])

if __name__ == "__main__":
    flow.register(project_name="default")
```



## Environment
<!-- Any additional information about your environment -->
Using local docker-compose Prefect server (`prefect server start`) with `LocalAgent`




Discussion:
Thanks for opening @novotl and for providing a reproducible example! I will look into this, it seems like the formatting kwargs aren't properly being passed through to where the result is loaded off of the state 🤔 
I was able to simplify the problem. I don't think it's the state dependency causing the problem, but the `None` result of an upstream task. Here is a simplified example of the same issue
```
import os
from typing import List, Optional

import prefect
from prefect import Flow, task
from prefect.engine.results import LocalResult


@task(name="A")
def task_a() -> Optional[List[int]]:
    return None # <-- this is causing an issue


@task(name="B")
def task_b(foo: List) -> None:
    prefect.context.logger.info(f"Task B {foo}")


result_directory = os.path.abspath(
    os.path.join(os.path.dirname(__file__), "..", "results")
)

result = LocalResult(
    dir=result_directory,
    location="{flow_name}/"
    "{scheduled_start_time:%d-%m_%H-%M-%S}/"
    "{task_full_name}-{task_run_id}.prefect_result",
)

with Flow(name="test_flow", result=result) as flow:
    a = task_a()
    b = task_b(a)

if __name__ == "__main__":
    flow.register(project_name="default")
    # flow.run()
```

Thanks @novotl! I have this on my docket to look into this week and will report back 👍 

Resolving patch:
diff --git a/src/prefect/engine/state.py b/src/prefect/engine/state.py
--- a/src/prefect/engine/state.py
+++ b/src/prefect/engine/state.py
@@ -119,7 +119,8 @@ def load_result(self, result: Result = None) -> "State":
 
         result_reader = result or self._result
 
-        known_location = self._result.location or getattr(result, "location", None)  # type: ignore
+        known_location = self._result.location  # type: ignore
+
         if self._result.value is None and known_location is not None:  # type: ignore
             self._result = result_reader.read(known_location)  # type: ignore
         return self


Test patch:
diff --git a/tests/engine/test_state.py b/tests/engine/test_state.py
--- a/tests/engine/test_state.py
+++ b/tests/engine/test_state.py
@@ -616,28 +616,6 @@ def read(self, *args, **kwargs):
         assert new_state.result is None
         assert new_state._result.location is None
 
-    @pytest.mark.parametrize("cls", all_states)
-    def test_state_load_result_reads_if_location_is_provided(self, cls):
-        class MyResult(Result):
-            def read(self, *args, **kwargs):
-                self.value = "bar"
-                return self
-
-        state = cls(result=Result())
-        assert state.message is None
-        assert state.result is None
-        assert state._result.location is None
-
-        new_state = state.load_result(MyResult(location="foo"))
-        assert new_state.message is None
-
-        if not new_state.is_mapped():
-            assert new_state.result == "bar"
-            assert new_state._result.location == "foo"
-        else:
-            assert new_state.result is None
-            assert not new_state._result.location
-
     @pytest.mark.parametrize("cls", all_states)
     def test_state_load_cached_results_calls_read(self, cls):
         """