Requirements engineering is concerned with the elicitation of high-level goals to be achieved by the system envisioned, the refinement of such goals and their operationalization into services and constraints, and the assignment of responsibilities for the resulting requirements to agents such as humans, devices, and software. Requirements engineering processes may often result in requirements and assumptions about agent behaviour that are too ideal; some of them are likely to be violated from time to time in the running system due to unexpected agent behaviour. The lack of anticipation of exceptional behaviors results in unrealistic, unachievable and/or incomplete requirements. As a consequence, the software developed from those requirements will inevitably result in poor performance, sometimes with critical consequences on the environment. This paper proposes systematic techniques for reasoning about obstacles to the satisfaction of goals, requirements, and assumptions elaborated in the requirements engineering process. These techniques are integrated into an existing method for goal-driven requirements elaboration with the aim of deriving more complete and realistic requirements. The concept of obstacle is first defined precisely. Formal techniques and domain-independent heuristics are then proposed for identifying obstacles from goal/assumption formulations and domain properties. The paper then discusses techniques for resolving obstacles by transformation of the goals, requirements and assumptions elaborated so far in the process, or by introduction of new ones. Numerous examples are given throughout the paper to suggest how the techniques can be usefully applied in practice.